孙鑫视频多线程的第一个例子----简易的售票程序
#include <Windows.h> #include <iostream> int ticket = 100; //定义互斥对象 /* 互斥对象属于内核对象,它能够准确保证线程拥有对单个资源的互斥访问 互斥对象包含一个使用数量 线程ID 计数器 ID用于标识系统中哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数 */ HANDLE hMutex; DWORD WINAPI FunProc_1(LPVOID lpParameter) { while(true) { //设置hMutex为未通知状态 //请求互斥对象 WaitForSingleObject(hMutex , INFINITE); if(ticket > 0) { Sleep(1); std::cout << "hThread1 ticket sell :" << ticket-- << std::endl; }else{ break; } //释放互斥对象,将互斥对象设置为通知对象 ReleaseMutex(hMutex); } return 0; } DWORD WINAPI FunProc_2(LPVOID lpParameter) { while(true) { //设置hMutex为未通知状态 //请求互斥对象 WaitForSingleObject(hMutex , INFINITE); if(ticket > 0) { Sleep(1); std::cout << "hThread2 ticket sell :" << ticket-- << std::endl; }else{ break; } //释放互斥对象,将互斥对象设置为通知对象 //当释放的时候,系统会判断当前线程ID和互斥对象hMutex内部的ID,相等才能释放,不等则不能释放 //谁拥有互斥对象,谁才能去释放互斥对象,这样才能成功释放 //ReleaseMutex实际上递减互斥对象的计数器 ReleaseMutex(hMutex); } return 0; } int main() { HANDLE hThread1 , hThread2; //创建线程 hThread1 = CreateThread(NULL , 0 , FunProc_1 , NULL , 0 , NULL); hThread2 = CreateThread(NULL , 0 , FunProc_2 , NULL , 0 , NULL); //关闭句柄并不是终止新创建线程,在主线程中关闭新创建线程的引用 //内核对象引用计数器减1,当内核对象的引用计数器为0时释放内核对象 //类似于c++中的句柄类中的引用计数 CloseHandle(hThread1); CloseHandle(hThread2); //创建/打开互斥对象 //TRUE调用该互斥对象获得所有权,反之是不获得 //当为FALSE时也就是主线程不获得hMutex的使用权 //当为TRUE时,主线程拥有了互斥对象,而主线程并没有释放,其他两个线程便得不到互斥对象的所有权 hMutex = CreateMutex(NULL , FALSE , NULL); Sleep(1000); return 0; }