互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID
和一个计数器。在这一节我们会用到三个函数,HANDLE WINAPI CreateMutexW( _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, _In_ BOOL bInitialOwner, _In_opt_ LPCWSTR lpName );lpMutexAttributes
BOOL WINAPI ReleaseMutex( _In_ HANDLE hMutex );hMutex
#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; void main(){ HANDLE hThread1; HANDLE hThread2; //创建互斥对象 hMutex = CreateMutex(NULL,true,NULL); ////计数器增加1,互斥对象内部计数器值为2 //WaitForSingleObject(hMutex, INFINITE); //创建线程 hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL); hThread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL); //关闭句柄,函数并没有终止新创建的线程,只是表示在主线程中对新创建的线程的引用不感兴趣,因此将它关闭 CloseHandle(hThread1); CloseHandle(hThread2); ReleaseMutex(hMutex); //main 函数主线程等待4秒 Sleep(4000); system("pause"); return; } //线程1的入口函数 DWORD WINAPI Fun1Proc(LPVOID lpParameter){ while (true) { //所请求的对象属于处于有信号状态,该函数才会返回,线程才能继续往下执行 WaitForSingleObject(hMutex, INFINITE); if (tickets > 0) cout << "thread1 sell ticket" << tickets-- << endl; else break; //释放当前线程对互斥对象的所有权,让该对象处于已通知状态 ReleaseMutex(hMutex); } return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter){ while (true) { //所请求的对象属于处于有信号状态,该函数才会返回,线程才能继续往下执行,注意调用WaitForSingleObject()的位置 WaitForSingleObject(hMutex, INFINITE); if (tickets > 0) cout << "thread2 sell ticket" << tickets-- << endl; else break; //释放当前线程对互斥对象的所有权,让该对象处于已通知状态,注意调用WaitForSingleObject()的位置 ReleaseMutex(hMutex); } return 0; }