参考:http://blog.csdn.net/morewindows/article/details/7470936
互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问。互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源。使用互斥量Mutex主要将用到四个函数。下面是这些函数的原型和使用说明。
第一个 CreateMutex
函数功能:创建互斥量(注意与事件Event的创建函数对比)
函数原型:
HANDLECreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes,
BOOLbInitialOwner,
LPCTSTRlpName
);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数用来确定互斥量的初始拥有者。如果传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零,所以互斥量处于未触发状态。如果传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用,处于触发状态。
第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。
函数访问值:
成功返回一个表示互斥量的句柄,失败返回NULL。
第二个打开互斥量
函数原型:
HANDLEOpenMutex(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName //名称
);
函数说明:
第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示互斥量句柄继承性,一般传入TRUE即可。
第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。
函数访问值:
成功返回一个表示互斥量的句柄,失败返回NULL。
第三个触发互斥量
函数原型:
BOOLReleaseMutex (HANDLEhMutex)
函数说明:
访问互斥资源前应该要调用等待函数,结束访问时就要调用ReleaseMutex()来表示自己已经结束访问,其它线程可以开始访问了。
最后一个清理互斥量
由于互斥量是内核对象,因此使用CloseHandle()就可以(这一点所有内核对象都一样)。
#include "stdio.h"
#include "process.h"
#include "windows.h"
long g_nNum;
unsigned int __stdcall Fun(void* pPM);
const int THREAD_NUM =10;
//互斥量与关键段
HANDLE g_hThreadParameter;
CRITICAL_SECTION g_csThreadCode;
int main()
{
printf(" 经典线程同步 互斥量Mutex\n");
//初始化互斥量与关键段 第二个参数为TRUE表示互斥量为创建线程所有
g_hThreadParameter =CreateMutex(NULL,FALSE,NULL);
InitializeCriticalSection(&g_csThreadCode);
HANDLE handle[THREAD_NUM];
g_nNum =0;
int i=0;
while(i<THREAD_NUM)
{
handle[i] =(HANDLE)_beginthreadex(NULL,0,Fun,&i,0,NULL);
WaitForSingleObject(g_hThreadParameter,INFINITE); //等待互斥量被触发
i++;
}
WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);
//销毁互斥量和关键段
CloseHandle(g_hThreadParameter);
DeleteCriticalSection(&g_csThreadCode);
for(i=0;i<THREAD_NUM;i++)
{
CloseHandle(handle[i]);
}
return 0;
}
unsigned int __stdcall Fun(void* pPM)
{
int nThreadNum =*(int*)pPM;
ReleaseMutex(g_hThreadParameter); //触发互斥量
Sleep(50); //some work should to do
EnterCriticalSection(&g_csThreadCode);
g_nNum++;
Sleep(0);
printf("线程编号为%d 全局资源值为%d\n",nThreadNum,g_nNum);
LeaveCriticalSection(&g_csThreadCode);
return 0;
}