一、临界区
临界区又称关键代码段,指的是一小段代码在代码执行前,它需要独占一些资源,只能在单独的进程中使用。程序中通常将多线程同时访问的某个资源的程序片段称为临界区。需要定义一个CRITICAL_SECTION类型的变量,然后调用InitializeCriticalSection函数对变量进行初始化。相对于互斥量来说,系统分配临界区对象的速度更快,所需的开销更小。
二、实例
定义一个全局的锁 CRITICAL_SECTION的实例和一个静态全局变量
CRITICAL_SECTIONcs;// 临界区的声明
static intn_AddValue = 0;//定义一个静态的全部变量n_AddValue
创建两个线程函数,代码实现如下
//第一个线程
UINT FirstThread(LPVOIDlParam)
{
EnterCriticalSection(&cs);//进入临界区,对需要保护的资源进行操作
for(int i =0; i<10;i++){
n_AddValue ++;
cout <<"n_AddValue in FirstThread is"<<n_AddValue << endl;
}
LeaveCriticalSection(&cs);//离开临界区
return 0;
}
//第二个线程
UINT SecondThread(LPVOIDlParam)
{
EnterCriticalSection(&cs);//进入临界区
for(int i =0; i<10;i++){
n_AddValue ++;
cout <<"n_AddValue in SecondThread is"<<n_AddValue << endl;
}
LeaveCriticalSection(&cs);//离开临界区
return 0;
}
在主函数添加以下代码
CWinThread *pFirstThread, *pSecondThread;//存储函数AfxBeginThread返回的CWinThread指针
InitializeCriticalSection(&cs);//初始化临界区
pFirstThread = AfxBeginThread(test->FirstThread, LPVOID(NULL));//启动第一个线程
pSecondThread = AfxBeginThread(test->SecondThread, LPVOID(NULL));//启动第二个线程
HANDLE hThreadHandle[2];//
hThreadHandle[0] = pFirstThread->m_hThread;
hThreadHandle[1] = pSecondThread->m_hThread;
//等待线程返回
WaitForMultipleObjects(2, hThreadHandle, TRUE, INFINITE);
三、临界区的原理
很多人对CRITICAL_SECTION的理解是错误的,认为CRITICAL_SECTION是锁定了资源,其实,CRITICAL_SECTION是不能够“锁定”资源的,它能够完成的功能,是同步不同线程的代码段。简单说,当一个线程执行了EnterCritialSection之后,cs里面的信息便被修改了,以指明哪一个线程占用了它。而此时,并没有任何资源被“锁定”。不管什么资源,其它线程都还是可以访问的(当然,执行的结果可能是错误的)。只不过,在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到EnterCritialSection语句的话,就会处于等待状态,相当于线程被挂起了。 这种情况下,就起到了保护共享资源的作用。
使用CriticalSection只适合在CriticalSection区域内处理的事情是非常简单的,耗时非常短的(程序级别的时间),如果处理事务用的时间比较长的话,就不适合用CriticalSection这种方式来解决问题
参考: