互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。
互斥对象包含一个使用数量,一个线程ID和一个计数器。其中:ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。
函数 CreateMutex 可以创建或打开一个命名的或者匿名的互斥对象,然后程序就可以利用该互斥对象完成线程的同步。函数原型声明如下:
1 2 3 4 5 |
HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes , BOOL bInitialOwner , LPCTSTR lpName ); |
参数含义如下:
lpMutexAttributes //一个指向 SECURITY_ATTRIBUTES 结构的指针,可以给该参数传递NULL值,让互斥对象的线程获得该对象的所有权。
bInitialOwner //BOOL类型,指定互斥对象初始的拥有者。如果该值为真,则创建这个互斥对象的线程获得该对象的所有权,否则该线程将不活的所创建的互斥对象的所有权。
lpName //指定互斥对象的命出,如果将此参数设置为NULL,则创建一个匿名的互斥对象。
如果调用成功,返回创建的互斥对象的句柄。如果创建的是命名的互斥对象,并且在调用函数前这个命名的互斥对象已经存在,则返回存在的这个互斥对象的句柄。
当线程对共享资源访问结束后,应释放该对象的所有权,也就是让该对象处于已通知状态。这时候需要调用ReleaseMutex函数,该函数将释放指定对象所有权,函数原型声明如下:
1 |
BOOL ReleaseMutex( HANDLE hMutex ); |
hMutex //需要释放的互斥对象的句柄。返回值为BOOL类型,成功返回非0值,否则返回0值。
线程必须主动请求共享对象的使用权才有可能获得所有权,这可以通过调用WaitForSingleObject函数实现。函数声明如下:
1 |
DWORD WaitForSingleObject( HANDLE hHandle , DWORD dwMilliseconds ); |
hHandle //所请求对象的句柄
dwMilliseconds //指定等待的时间间隔,以毫秒为单位。如果指定的时间间隔已过,即使所请求的对象仍处于无信号状态,函数也会返回。如果将此参数设置为0,那么函数会测试该对象的状态并立即返回,如果将参数设置为INFINITE,则函数会永远等待,直到对象有信号返回。
调用 WaitForSingleObject 函数后,该函数会一直等待,只有在两种情况下才会返回。
- 指定的对象变成有信号状态
- 知道的等待时间间隔已过
如果调用成功,那么函数的返回值将表面引起该函数返回的事件:
返回值 | 说明 |
WAIT_OBJECT_0 | 所请求的对象是有信号状态 |
WAIT_TIMEOUT | 指定的时间间隔已过,且所请求的对象是无信号状态 |
WAIT_ABANDONED | 所请求的对象是一个互斥对象,并且先前拥有该对象的线程在终止前没有释放该对象。这时,该对象的所有权将授予当前调用线程,并且将该互斥对象设置为无信号状态 |
互斥对象实例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#include <windows.h> #include <iostream> using namespace std; DWORD WINAPI Fun1Proc( LPVOID lpParameter ); DWORD WINAPI Fun2Proc( LPVOID lpParameter ); int index = 0; int tickets = 100; HANDLE hMutex; int main() { HANDLE hThread1; HANDLE hThread2; hMutex = CreateMutex( NULL , FALSE , NULL ); hThread1 = CreateThread( NULL , 0 , Fun1Proc , NULL , 0 , NULL ); hThread2 = CreateThread( NULL , 0 , Fun2Proc , NULL , 0 , NULL ); CloseHandle( hThread1 ); CloseHandle( hThread2 ); //cout << "Main Thread is running.\n"; Sleep( 10000 ); return 0; } DWORD WINAPI Fun1Proc( LPVOID lpParameter ) { //cout << "Thread1 is running." << endl; while(1) { WaitForSingleObject( hMutex , INFINITE ); if(tickets > 0) { Sleep( 1 ); cout << "Thread1 sell ticket :" << tickets-- << endl; } else { break; } ReleaseMutex( hMutex ); } return 0; } DWORD WINAPI Fun2Proc( LPVOID lpParameter ) { //cout << "Thread2 is running." << endl; while(1) { WaitForSingleObject( hMutex , INFINITE ); if(tickets > 0) { Sleep( 1 ); cout << "Thread2 sell ticket :" << tickets-- << endl; } else { break; } ReleaseMutex( hMutex ); } return 0; } |
对于互斥对象来说,谁拥有,谁释放。
哟呵,windows开发
只是才接触罢了…