是否需要临界区?

Is CRITICAL SECTION required?

本文关键字:临界区 是否      更新时间:2023-10-16

我得到了下面的代码从谷歌搜索,因为我试图学习多线程。我在使用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可以防止代码块同时被两个或多个线程运行。

在大多数情况下,您不会看到有或没有差异,它的存在是为了保护共享资源不被运行,例如:

想象两个线程同时访问像内存块这样的资源,一个线程从它读取图像,而另一个线程正在向它写入图像。读取线程将得到一个损坏的图像。

我建议你多读一些关于多线程的书,以便更好地理解这个概念,以及如何在多线程应用程序中使用同步对象来控制流。

  1. http://www.codeproject.com/Articles/7953/Thread-Synchronization-for-Beginners
  2. http://msdn.microsoft.com/en-us/library/windows/desktop/ms681924 (v = vs.85) . aspx