线程同步之关键段

[什么是关键段]
  关键段(Critical section)是一小段代码,它在执行之前需要独占一些共享资源的访问权。这种方式可以上多行代码以"原子方式"来对资源进行操控。这里的原子方式,是指代码知道除了当前线程以外,没有其他任何线程会同时访问该资源。

[什么时候使用]
当我们有一个资源要让多个线程访问时;
当不能用Interlocked函数解决同步问题时;

[怎么使用关键段]

#include <Windows.h>

DWORD WINAPI FirstThread(PVOID pvParam);
DWORD WINAPI SecondThread(PVOID pvParam);

#define COUNTNUMBER  10
int g_Number = 0;
CRITICAL_SECTION    g_cs;

int WINAPI WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
{
    char cThreadBuffer[260] = {NULL};

    HANDLE hFirstThread = CreateThread(NULL, 0, FirstThread, NULL, 0, NULL);
    HANDLE hSecondThread = CreateThread(NULL, 0, SecondThread, NULL, 0, NULL);

    wsprintf(cThreadBuffer, "%d", g_Number);
    MessageBox(0, cThreadBuffer, "Tips", MB_OK);

    return 0;
}

DWORD WINAPI FirstThread(PVOID pvParam)
{
    //
    //使用前必须初使化
    //
    InitializeCriticalSection(&g_cs);
    EnterCriticalSection(&g_cs);
    g_Number = 0;
    for (int n=0; n< COUNTNUMBER; n++)
    {
        g_Number += n;
    }
    char cFirstThreadBuffer[260] = {NULL};
    wsprintf(cFirstThreadBuffer, "First:%d", g_Number);
    MessageBox(0, cFirstThreadBuffer, "Tips", MB_OK);
    LeaveCriticalSection(&g_cs);
    return (g_Number);
}

DWORD WINAPI SecondThread(PVOID pvParam)
{
    //
    //使用前必须初使化
    //
    InitializeCriticalSection(&g_cs);
    EnterCriticalSection(&g_cs);
    g_Number = 0;
    for (int n= 0;n< COUNTNUMBER; n++)
    {
        g_Number += n;
    }
    char cSecondThreadBuffer[260] = {NULL};
    wsprintf(cSecondThreadBuffer, "Second:%d", g_Number);
    MessageBox(0, cSecondThreadBuffer, "Tips", MB_OK);
    LeaveCriticalSection(&g_cs);
    return (g_Number);
}

首先定义了一个g_cs的CRITICAL_SECTION结构,把任何需要修改共享资源(g_Number)的代码放到EnterCriticalSection和LeaveCriticalSection之间。
如果忘了任何线程哪怕一个地方没有加EnterCriticalSection和LeaveCriticalSection,共享资源都有被破坏的可能。

[缺点]
最大缺点是在于它们无法用来在多个进程之间对线程进行同步

 

2012-10-25

 

posted @ 2012-10-25 23:05  markro  阅读(138)  评论(0)    收藏  举报