C++ 多线程中互斥信号量的使用


互斥信号量mutex

互斥信号量是一种内核对象,它用来保证一个线程独占一个资源的访问。在使用互斥信号量的时候,有四个主要的函数:
(1)CreateMutex,创建互斥信号量。

函数原型如下所示:

HANDLE CreateMutex(

  LPSECURITY_ATTRIBUTES lpMutexAttributes,

  BOOL bInitialOwner,     

  LPCTSTR lpName

);

第一个参数一般传入NULL,表示安全控制。
第二个参数确定互斥量的拥有者,传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用。
第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。
(2)OpenMutex,打开互斥信号量

函数原型如下所示:

HANDLE OpenMutex(

 DWORD dwDesiredAccess,

 BOOL bInheritHandle,

 LPCTSTR lpName

);

函数说明:
第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS
第二个参数表示互斥量句柄继承性,一般传入TRUE即可。
第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。

函数返回值:
成功返回一个表示互斥量的句柄,失败返回NULL。

(3)ReleaseMutex ,触发互斥信号量

函数原型如下所示:

BOOL ReleaseMutex(
     HANDLE hMutex
);

访问完互斥资源调用该函数,表示自己已经使用完互斥资源。

(4)CloseHandle,清理互斥量

函数原型如下所示:

BOOL CloseHandle(
     HANDLE hMutex
);

对于互斥量来讲如果正在被使用则为无信号状态,被释放后变为有信号状态。当等待成功后 WaitForSingleObject 函数会将互斥量置为无信号状态,这样其他的线程就不能获得使用权而需要继续等待。


互斥量使用示例

以两个窗口卖票为例,总票数100。

#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI ThreadFun1(LPVOID para);
DWORD WINAPI ThreadFun2(LPVOID para);

int tickets = 100;

void main()
{
    HANDLE thread1;
    HANDLE thread2;
    thread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL);
    thread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);
    WaitForSingleObject(thread1, INFINITE);
    WaitForSingleObject(thread2, INFINITE);
    CloseHandle(thread1);
    CloseHandle(thread2);
    system("pause");
}

DWORD WINAPI ThreadFun1(LPVOID para)
{
    while (TRUE)
    {
        if (tickets>0)
        {
            Sleep(20);
            cout << "thread1 sell ticket : " << tickets-- << endl;
        }
        else
            break;
    }
    return 0;
}

DWORD WINAPI ThreadFun2(LPVOID para)
{
    while (TRUE)
    {
        if (tickets>0)
        {
            Sleep(20);
            cout << "thread2 sell ticket : " << tickets-- << endl;
        }
        else
            break;
    }
    return 0;
}

这里写图片描述
从运行结果可以看到,两个窗口同时卖票出现了混乱,运行结果错误。


下面使用互斥信号量对票数进行加锁操作。

#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI ThreadFun1(LPVOID para);
DWORD WINAPI ThreadFun2(LPVOID para);

int tickets = 100;
HANDLE mutex;
void main()
{
    HANDLE thread1;
    HANDLE thread2;
    mutex = CreateMutex(NULL, 0, NULL);
    thread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL);
    thread2 = CreateThread(NULL, 0, ThreadFun2, NULL, 0, NULL);
    WaitForSingleObject(thread1, INFINITE);
    WaitForSingleObject(thread2, INFINITE);
    CloseHandle(thread1);
    CloseHandle(thread2);
    system("pause");
}

DWORD WINAPI ThreadFun1(LPVOID para)
{
    while (TRUE)
    {
        WaitForSingleObject(mutex, INFINITE);
        if (tickets>0)
        {
            Sleep(20);
            cout << "thread1 sell ticket : " << tickets-- << endl;
        }
        else
            break;
        ReleaseMutex(mutex);
    }
    return 0;
}

DWORD WINAPI ThreadFun2(LPVOID para)
{
    while (TRUE)
    {
        WaitForSingleObject(mutex, INFINITE);
        if (tickets>0)
        {
            Sleep(20);
            cout << "thread2 sell ticket : " << tickets-- << endl;
        }
        else
            break;
        ReleaseMutex(mutex);
    }
    return 0;
}

这里写图片描述
对票数加锁之后,运行结果正确。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值