互斥信号量是一种内核对象,它用来保证一个线程独占一个资源的访问。在使用互斥信号量的时候,有四个主要的函数: (1)CreateMutex,创建互斥信号量。
函数原型如下所示:
HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName );第一个参数一般传入NULL,表示安全控制。 第二个参数确定互斥量的拥有者,传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用。 第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。 (2)OpenMutex,打开互斥信号量
函数原型如下所示:
HANDLE OpenMutex( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );函数说明: 第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS 第二个参数表示互斥量句柄继承性,一般传入TRUE即可。 第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。
函数返回值: 成功返回一个表示互斥量的句柄,失败返回NULL。
(3)ReleaseMutex ,触发互斥信号量
函数原型如下所示:
BOOL ReleaseMutex( HANDLE hMutex );访问完互斥资源调用该函数,表示自己已经使用完互斥资源。
(4)CloseHandle,清理互斥量
函数原型如下所示:
BOOL CloseHandle( HANDLE hMutex );对于互斥量来讲如果正在被使用则为无信号状态,被释放后变为有信号状态。当等待成功后 WaitForSingleObject 函数会将互斥量置为无信号状态,这样其他的线程就不能获得使用权而需要继续等待。
以两个窗口卖票为例,总票数100。
#include <windows.h> #include <iostream> using namespace std; DWORD WINAPI ThreadFun1(LPVOID para); DWORD WINAPI ThreadFun2(LPVOID para); int tickets = 100; void main() { HANDLE thread1; HANDLE thread2; thread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL); thread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL); WaitForSingleObject(thread1, INFINITE); WaitForSingleObject(thread2, INFINITE); CloseHandle(thread1); CloseHandle(thread2); system("pause"); } DWORD WINAPI ThreadFun1(LPVOID para) { while (TRUE) { if (tickets>0) { Sleep(20); cout << "thread1 sell ticket : " << tickets-- << endl; } else break; } return 0; } DWORD WINAPI ThreadFun2(LPVOID para) { while (TRUE) { if (tickets>0) { Sleep(20); cout << "thread2 sell ticket : " << tickets-- << endl; } else break; } return 0; }从运行结果可以看到,两个窗口同时卖票出现了混乱,运行结果错误。
下面使用互斥信号量对票数进行加锁操作。
#include <windows.h> #include <iostream> using namespace std; DWORD WINAPI ThreadFun1(LPVOID para); DWORD WINAPI ThreadFun2(LPVOID para); int tickets = 100; HANDLE mutex; void main() { HANDLE thread1; HANDLE thread2; mutex = CreateMutex(NULL, 0, NULL); thread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL); thread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL); WaitForSingleObject(thread1, INFINITE); WaitForSingleObject(thread2, INFINITE); CloseHandle(thread1); CloseHandle(thread2); system("pause"); } DWORD WINAPI ThreadFun1(LPVOID para) { while (TRUE) { WaitForSingleObject(mutex, INFINITE); if (tickets>0) { Sleep(20); cout << "thread1 sell ticket : " << tickets-- << endl; } else break; ReleaseMutex(mutex); } return 0; } DWORD WINAPI ThreadFun2(LPVOID para) { while (TRUE) { WaitForSingleObject(mutex, INFINITE); if (tickets>0) { Sleep(20); cout << "thread2 sell ticket : " << tickets-- << endl; } else break; ReleaseMutex(mutex); } return 0; }对票数加锁之后,运行结果正确。