windows提供了四种多任务同步方法:
1.临界区(critical section)
2.事件(event)
3.信号量(Semaphore)
4.互斥量(Mutex)
其中,临界区是用户对象,效率较高,但只能用于同一进程的多线程同步,其他方法是内核对象,可以用于多进程间的线程同步.本文介绍临界区和互斥量的使用方法.思路如下:
-windows api临界区
-windows api互斥量
-MFC临界区类
-MFC互斥量类
-注意事项
1.windows api临界区
在每个访问共享资源的代码片段前,调用"进入"临界区函数,访问完成后,再调用"离开"临界区函数.
首先要,定义全局临界区变量:
CRITICAL_SECTION g_crit;
在一个函数中,初始化临界区:(只进行一次)
InitializeCriticalSection(&g_crit);
在访问全局资源前,进入临界区,代码段加入:
EnterCriticalSection(&g_crit);
则其他同样调用该函数和参数的线程,会处于等待状态.
访问完成后,离开临近区,代码段加入:
LeaveCriticalSection(&g_crit);
其他线程就可以继续执行.
2.windows api互斥量
与临界区使用方法类似,不同的是,由于是内核维护,所以无需使用全局变量的方式,而是使用互斥量句柄.
创建互斥量--等待持有资源--释放资源占有.
每个创建的互斥量名字不可相同.否则,系统会返回原有的句柄.
创建互斥量:
HANDLE h_mutex = CreateMutex(NULL, FALSE, TEXT("pbm"));
参数2表示是否立即持有资源,一般取FALSE,不立即持有.
等待持有资源:
WaitForSingleObject(h_mutex,INFINITE);
释放资源占有:
ReleaseMutex(h_mutex);
3.MFC临界区
MFC提供了类:CCriticalSection代表临界区.
增加头文件:#include "afxmt.h"
定义全局的临界区:
CCriticalSection g_criSection;
使用类的成员函数,即可实现进入临界区,离开临界区的操作:
g_criSection.Lock(); /* ...用户代码... */ g_criSection.UnLock();
4.MFC互斥量
MFC提供类:CMutex代表互斥量.
CMutex( BOOL bInitiallyOwn = FALSE, //一般默认,代表不占有(非锁定) LPCTSTR lpszName = NULL, //互斥体名 LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );定义互斥体对象:
CMutex test_mutex(FALSE,"pbm");
使用成员函数,访问共享资源:
test_mutex.Lock(); /* ...用户代码... */ test_mutex.Unlock();
5.注意事项
访问共享资源的代码段,如果未使用临界区或互斥量技术,即使其他代码段均使用临界区或互斥量保护共享资源,依然无法实现线程互斥.
所以,在每个访问共享资源的代码片段,都要添加"出入锁".