Mutex互斥量也是一个内核对象,用来确保每个线程独占一个资源的访问,互斥量与临界区相似,但互斥量可以用于不同进程间的线程互访资源。
主要用到四个函数:
创建互斥量(注意与事件Event的创建函数对比)
函数原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数用来确定互斥量的初始拥有者。如果传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零,所以互斥量处于未触发状态。如果传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用,处于触发状态。
第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。
成功返回一个表示互斥量的句柄,失败返回NULL。
打开互斥量
函数原型:
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName //名称
);
函数说明:
第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS。
第二个参数表示互斥量句柄继承性,一般传入TRUE即可。
第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。
成功返回一个表示互斥量的句柄,失败返回NULL。
触发互斥量
函数原型:
BOOLReleaseMutex (HANDLEhMutex)
函数说明:
访问互斥资源前应该要调用等待函数,结束访问时就要调用ReleaseMutex()来表示自己已经结束访问,其它线程可以开始访问了。
清理互斥量
由于互斥量是内核对象,因此使用CloseHandle()就可以
互斥量不能解决同步问题。
互斥量能够用于多个进程间的线程互斥,并能完美解决某进程意外终止造成的遗弃问题。
//当互斥量计数为0时,表示处于触发状态,当互斥量计数为1时,表示未触发状态
HANDLE mutex = INVALID_HANDLE_VALUE;
typedef struct param{
int a;
bool b;
double c;
string d;
};
unsigned int __stdcall threadfun1(LPVOID p){
Sleep(100);
//调用等待互斥量未触发,将其有未触发改为触发
WaitForSingleObject(mutex,INFINITE);
param* funparam = (param*) p;
cout<<"fun1 running:"<<funparam->d<<endl;
funparam->c *= funparam->a;
cout<<"ans:"<<funparam->c<<endl;
//释放互斥量,改为未触发
ReleaseMutex(mutex);
return 0;
}
DWORD __stdcall threadfun2(LPVOID p){
Sleep(100);
//调用等待互斥量未触发,将其有未触发改为触发
WaitForSingleObject(mutex,INFINITE);
param* funparam = (param*) p;
cout<<"fun2 running:"<<funparam->d<<endl;
funparam->c /= funparam->a;
cout<<"ans:"<<funparam->c<<endl;
//释放互斥量,改为未触发
ReleaseMutex(mutex);
return 0;
}
int main(){
param p={5,true,9.995,"hello world"};
//A表示字符串使用的是ASCII编码集,默认为UNICODE,即W。
//第二个参数为false,表示互斥量未触发,当为true表示已触发。
mutex = CreateMutexA(NULL,false,"MUTEX");
//对于进程间的互斥,在一个进程创建互斥量,然后在另外一个进程打开互斥量
mutex = OpenMutexA(MUTEX_ALL_ACCESS,true,"MUTEX");
HANDLE newthread1 = (HANDLE)_beginthreadex(NULL,0,threadfun1,&p,0,NULL);
HANDLE newthread2 = CreateThread(NULL,0,threadfun2,&p,0,NULL);
WaitForSingleObject(newthread2,INFINITE);
WaitForSingleObject(newthread1,INFINITE);
CloseHandle(mutex);
system("PAUSE");
}