windows多线程系列002 利用互斥对象实现线程同步
接着上一篇文章我们继续讨论多线程的问题,这一次我们利用互斥对象(mutex)来解决火车站售票同步问题。1 利用互斥对象实现线程同步互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID和一个计数器。在这一节我们会用到三个函数,(1)创建互斥对象CreateMutex函数的原型声明HANDLEWINAPICreat
·
接着上一篇文章我们继续讨论多线程的问题,这一次我们利用互斥对象(mutex)来解决火车站售票同步问题。
一个指向SECURITY_ATTRIBUTES结构的指针,可以给该参数传递NULL值,让互斥对象使用默认的安全性。
bInitialOwner
BOOL类型,指定互斥对象初始的拥有者。如果该值为真,则创建这个互斥对象的线程获得该对象的所有权;否则,该线程不获得所创建的互斥对象的所有权。
lpName
指定互斥对象的名称。如果此参数为NULL,则创建一个匿名的互斥对象。
需要释放的互斥对象的句柄
WaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
hHandle
所请求对象的句柄
dwMilliseconds
指定等待的时间间隔,以毫秒为单位
返回值:
WAIT_OBJECT_0: 指定对象的状态被置为信号状态。
WAIT_TIMEOUT: 超时,并且对象的状态为非信号态。
WAIT_ABANDONED: 指定对象是互斥对象,在线程被终止前,线程没有释放互斥对象。互斥对象的所属关系被授予调用线程,并且该互斥对象被置为非信号态。
WAIT_FAILED: 调用失败。
下面看我们是如何使用互斥对象实现火车站售票系统的同步问题.
1 利用互斥对象实现线程同步
互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID
和一个计数器。在这一节我们会用到三个函数,(1)创建互斥对象CreateMutex函数的原型声明
HANDLE
WINAPI
CreateMutexW(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
_In_ BOOL bInitialOwner,
_In_opt_ LPCWSTR lpName
);
lpMutexAttributes
一个指向SECURITY_ATTRIBUTES结构的指针,可以给该参数传递NULL值,让互斥对象使用默认的安全性。
bInitialOwner
BOOL类型,指定互斥对象初始的拥有者。如果该值为真,则创建这个互斥对象的线程获得该对象的所有权;否则,该线程不获得所创建的互斥对象的所有权。
lpName
指定互斥对象的名称。如果此参数为NULL,则创建一个匿名的互斥对象。
(2)释放指定对象的所有权ReleaseMutex函数的原型声明
BOOL
WINAPI
ReleaseMutex(
_In_ HANDLE hMutex
);
hMutex
需要释放的互斥对象的句柄
(3)请求共享对象使用权函数WaitForSingleObject
WINAPIWaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
hHandle
所请求对象的句柄
dwMilliseconds
指定等待的时间间隔,以毫秒为单位
返回值:
WAIT_OBJECT_0: 指定对象的状态被置为信号状态。
WAIT_TIMEOUT: 超时,并且对象的状态为非信号态。
WAIT_ABANDONED: 指定对象是互斥对象,在线程被终止前,线程没有释放互斥对象。互斥对象的所属关系被授予调用线程,并且该互斥对象被置为非信号态。
WAIT_FAILED: 调用失败。
下面看我们是如何使用互斥对象实现火车站售票系统的同步问题.
#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;
}
更多推荐
已为社区贡献6条内容
所有评论(0)