孙鑫视频多线程的第一个例子----简易的售票程序
#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;
}