是否需要临界区?
Is CRITICAL SECTION required?
我得到了下面的代码从谷歌搜索,因为我试图学习多线程。我在使用CRITICAL SECTION和不使用CRITICAL SECTION的情况下运行代码,但是在执行了这两种情况之后,我不明白为什么这段代码的作者使用CRITICAL SECTION。
static unsigned int counter = 100;
static bool alive = true;
CRITICAL_SECTION cs;
static unsigned __stdcall Sub(void *args)
{
while(alive)
{
EnterCriticalSection(&cs);
cout << "[Sub(" << counter << ")]---" << endl;
counter -= 10;
LeaveCriticalSection(&cs);
Sleep(500);
}
return 0;
}
static unsigned __stdcall Add(void *args)
{
while(alive)
{
EnterCriticalSection(&cs);
cout << "[Add(" << counter << ")]+++" << endl;
counter += 10;
LeaveCriticalSection(&cs);
Sleep(500);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection(&cs);
unsigned add;
HANDLE hAdd = (HANDLE)_beginthreadex(0,0,&Add,0,CREATE_SUSPENDED, &add);
assert(hAdd != 0);
unsigned sub;
HANDLE hSub = (HANDLE)_beginthreadex(0,0,&Sub,0,CREATE_SUSPENDED, &sub);
assert(hSub != 0);
//start threads
ResumeThread(hAdd);
ResumeThread(hSub);
//let threads run for 10 seconds
Sleep(3000);
alive = false;
WaitForSingleObject(hSub, INFINITE);
CloseHandle(hSub);
WaitForSingleObject(hAdd, INFINITE);
CloseHandle(hAdd);
return 0;
}
您有两个并行运行的线程,都是读(cout << "[Sub(" << counter << ")]---" << endl
)和读/写(counter -= 10)
)一个共享变量。如果在读取和写入之间,另一个线程写入该值,您认为会发生什么?如果您试图根据counter
的值做出决定,当同一变量的两个不同读取可能返回不同的值时,该怎么办?
下列顺序可能(可能也可能不)出现:
thread SUB: read counter [say, 100]
thread ADD: read counter [100]
thread ADD: write counter <- 110
thread SUB: write counter <- 90
对于CRITICAL_SECTION,您有:
thread SUB: read counter [say, 100]
thread SUB: write counter <- 90
thread ADD: read counter [90]
thread ADD: write counter <- 100
或者:
thread ADD: read counter [100]
thread ADD: write counter <- 110
thread SUB: read counter [110]
thread SUB: write counter <- 100
无论如何,如果使用CRITICAL_SECTION,最终结果是100,如果不使用,最终结果可能是90。
CRITICAL_SECTION允许代码块作为一个"工作单元"执行,而不会受到阻塞在同一CRITICAL_SECTION上的另一个线程的干扰。
CRITICAL_SECTION是一个简单的多线程同步机制。使用CRITICAL_SECTION可以防止代码块同时被两个或多个线程运行。
在大多数情况下,您不会看到有或没有差异,它的存在是为了保护共享资源不被运行,例如:
想象两个线程同时访问像内存块这样的资源,一个线程从它读取图像,而另一个线程正在向它写入图像。读取线程将得到一个损坏的图像。
我建议你多读一些关于多线程的书,以便更好地理解这个概念,以及如何在多线程应用程序中使用同步对象来控制流。
- http://www.codeproject.com/Articles/7953/Thread-Synchronization-for-Beginners
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms681924 (v = vs.85) . aspx
相关文章:
- 在同步问题中,弱指针可以代替互斥锁或临界区吗?
- 多线程环境下,其他线程永远无法访问临界区
- 如果一个线程在临界区上调用Acquire(),如果另一个线程调用Release(),该锁会被释放吗?
- 是否需要临界区?
- 当我的堆栈加倍时,它会给我临界区错误!_ctrlvalidHeappointer
- 确定Windows线程是否处于临界区或类似的位置
- 这段代码是一个工作的临界区包装器类吗?
- 临界区通过constexpr
- 临界区队列
- 出乎意料的性能提升与OpenMP临界区
- 如何使用Boost创建临界区?
- 临界区最简单的实现
- 由两个线程访问的共享队列的临界区代码是什么?
- c++ 11有临界区吗?
- 如何避免临界区和SendMessage之间的死锁
- Windows临界区公平性
- 线程同步-临界区或互斥锁
- 是否寄存器读/写需要临界区保护
- 如何在两个类之间共享单个临界区
- 什么是临界区