windows多线程系列002 利用互斥对象实现线程同步

    接着上一篇文章我们继续讨论多线程的问题,这一次我们利用互斥对象(mutex)来解决火车站售票同步问题。

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

WINAPI
WaitForSingleObject(
_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;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DaveBobo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值