天天看点

利用CRITICAL_SECTION实现进程通信

定义临界区变量

CRITICAL_SECTION gCriticalSection;

通常情况下,CRITICAL_SECTION 结构体应该被定义为全局变量, 以便于进程中的所有线程方便地按照变量名来引用该结 构体。

初始化临界区

VOID WINAPI InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection //指向程序员定义的CRITICAL_SECTION 变量 );

该函数用于对pcs 所指的 CRITICAL_SECTION 结构体进行初始化。该函数只是设置了一些成员变量,它的运行一般不会 失败,因此它采用了 VOID 类型的返回值。该函数必须在任何线程调用 EnterCriticalSection 函数之前被调用,如果一个线程试 图进入一个未初始化的 CRTICAL_SECTION,那么结果将是很难预计的。

删除临界区

VOID WINAPI DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection //指向一个不再需要的 CRITICAL_SECTION 变量 );

进入临界区

VOID WINAPI EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection //指向一个你即将锁定的 CRITICAL_SECTION 变量 );

离开临界区

VOID WINAPI LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection //指向一个你即将离开的 CRITICAL_SECTION 变量 );

使用临界区编程的一般方法是:

void UpdateData() { EnterCriticalSection(&gCriticalSection); ...//dosomething LeaveCriticalSection(&gCriticalSection); }

关于临界区的使用,有下列注意点:

(1)每个共享资源使用一个 CRITICAL_SECTION 变量;

(2)不要长时间运行关键代码段,当一个关键代码段长时间运行时,其他线程就会进入等待状态,这会降低应用程序的运

行性能;

(3)如果需要同时访问多个资源,则可能连续调用 EnterCriticalSection;

(4)CriticalSection 不是 OS核心对象,如果进入临界区的线程"挂"了,将无法释放临界资源。这个缺点在 Mutex 中得到 了弥补。

例子:

#include <Windows.h>

#include <process.h>

#include <stdio.h>

#include <stdlib.h>

int v = 0;//临界区数据

volatile bool stop_thread = false;

CRITICAL_SECTION g_CS;//锁

UINT WINAPI ThreadOneProc(LPVOID pParam)

{

    while(!stop_thread)

    {

        EnterCriticalSection( &g_CS );//进入临界区

        printf("one: %d\n",v++);

        LeaveCriticalSection( &g_CS );//退出临界区

        Sleep(500);

    }

    return 1;

}

UINT WINAPI ThreadTwoProc(LPVOID pParam)

{

    while(!stop_thread)

    {

        EnterCriticalSection( &g_CS );

        if (v>0)

        {

            printf("two: %d\n",v--);

        }

        LeaveCriticalSection( &g_CS );

        Sleep(10);

    }

    return 2;

}

int main()

{

    InitializeCriticalSection( &g_CS );//创建临界区

    _beginthreadex(NULL,0,ThreadOneProc,0,0,0);//创建线程

    _beginthreadex(NULL,0,ThreadTwoProc,0,0,0);

    system("pause");

    DeleteCriticalSection(&g_CS);

    return 0;

}