c++多线程重点难点(三)Mutex

c++多线程重点难点(三)Mutex互斥量互斥量是一个内核对象,它用来确保一个线程独占一个资源的访问。互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源。使用互斥量Mutex主要将用到四个函数创建互斥量:CreateMutex函数返回一个互斥量的句柄或者NULL打开互斥量:OpenMutex函数返回一个互斥量的句柄或者NULL触发互斥量:ReleaseMutex访问互斥资源前应该要调用等待函数,结

大家好,又见面了,我是你们的朋友全栈君。

互斥量

互斥量是一个内核对象,它用来确保一个线程独占一个资源的访问。互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源。使用互斥量Mutex主要将用到四个函数

创建互斥量:CreateMutex
函数返回一个互斥量的句柄或者NULL

打开互斥量:OpenMutex
函数返回一个互斥量的句柄或者NULL

触发互斥量:ReleaseMutex
访问互斥资源前应该要调用等待函数,结束访问时就要调用ReleaseMutex()来表示自己已经结束访问,其它线程可以开始访问了。

销毁互斥量:CloseHandle
内核对象的销毁都可以用这个方法

要注意的是:

1.互斥量解决不了线程间的同步问题
2.互斥量和关键段一样拥有“线程拥有权”
3.遗弃特性:
比如有一个占用互斥量的线程在调用ReleaseMutex()触发互斥量前就意外终止了(相当于该互斥量被“遗弃”了),那么所有等待这个互斥量的线程是否会由于该互斥量无法被触发而一直阻塞?这显然不合理。因为占用某个互斥量的线程既然终止了那足以证明它不再使用被该互斥量保护的资源,所以这些资源完全并且应当被其它线程来使用。因此在这种“遗弃”情况下,系统自动把该互斥量内部的线程ID设置为0,并将它的递归计数器复置为0,表示这个互斥量被触发了。然后系统将“公平地”选定一个等待线程来完成调度(被选中的线程的WaitForSingleObject()会返回WAIT_ABANDONED_0)。

下面有两个程序用来实现mutex的遗弃特性,运用这两个程序时要先启动程序一再启动程序二,将程序一中//exit(0);前面的注释符号去掉,这样程序一在触发互斥量之前就会因为执行exit(0);语句而且退出,程序二会收到WAIT_ABANDONED消息并输出“拥有互斥量的进程意外终止”:

//程序一
#include <stdio.h>
#include <conio.h>
#include <windows.h>
const char MUTEX_NAME[] = "Mutex_MoreWindows";
int main()
{
    HANDLE hMutex = CreateMutex(NULL, TRUE, MUTEX_NAME); //创建互斥量
    printf("互斥量已经创建,现在按任意键触发互斥量\n");
    getch();
    //exit(0);
    ReleaseMutex(hMutex);
    printf("互斥量已经触发\n");
    CloseHandle(hMutex);
    return 0;
}
//程序二
#include <stdio.h>
#include <windows.h>
const char MUTEX_NAME[] = "Mutex_MoreWindows";
int main()
{
    HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, MUTEX_NAME); //打开互斥量
    if (hMutex == NULL)
    {
        printf("打开互斥量失败\n");
        return 0;
    }
    printf("等待中....\n");
    DWORD dwResult = WaitForSingleObject(hMutex, 20 * 1000); //等待互斥量被触发
    switch (dwResult)
    {
    case WAIT_ABANDONED:
        printf("拥有互斥量的进程意外终止\n");
        break;

    case WAIT_OBJECT_0:
        printf("已经收到信号\n");
        break;

    case WAIT_TIMEOUT:
        printf("信号未在规定的时间内送到\n");
        break;
    }
    CloseHandle(hMutex);
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/153218.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • betterIntellij 最新激活码【在线破解激活】[通俗易懂]

    betterIntellij 最新激活码【在线破解激活】,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • java工具类——验证码(VerifyCode)[通俗易懂]

    java工具类——验证码(VerifyCode)[通俗易懂]importjava.awt.BasicStroke;importjava.awt.Color;importjava.awt.Font;importjava.awt.Graphics2D;importjava.awt.image.BufferedImage;importjava.io.FileNotFoundException;importjava.io.IOExcept

  • 大数据DBA:大数据数据库管理做什么

    大数据DBA:大数据数据库管理做什么在大数据快速发展的大背景下,大数据相关的岗位需求也在增多,并且随着大数据业务的扩展,大数据技术团队的工作,也开始走向岗位细分,比如说在大数据储存阶段,也有专门的大数据DBA岗位。今天我们就来了解一下大数据数据库管理做什么?DBA,DBA是英文DatabaseAdministrator的简称,也就是数据库管理员,主要工作任务是负责维护和管理数据库服务器。数据库管理员,是需要关注数据,也需要关注库,即需要关注数据与服务,要关心如何操作数据库(程序),从而来保障好数据库。这就要求DBA不要只做好.

  • let暂时性死区

    let暂时性死区只要块级作用域内存在let命令,他所声明的变量就绑定这个区域,不再受外部的影响。vartmp=123;if(true){tmp=’abc’;lettmp;}抛出错误:ReferenceError上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。ES…

  • 镁光闪存颗粒对照表_内存颗粒版本判断方法和编号解析(三星、美光、海力士)…

    镁光闪存颗粒对照表_内存颗粒版本判断方法和编号解析(三星、美光、海力士)…因为昨天chh看到一个人还在用土办法去判断美光颗粒版本加上前面B站也有人问我怎么去判断内存颗粒版本使用今天就抽空写一下。1.三星三星官方命名文件如下:实例:第一行:“SEC843”重要信息为843代表内存颗粒生产日期第二行:“K4A4G08”重要信息为4G08代表内存颗粒容量和位宽(AG代表容量为16Gb)第三行:“5WTBCTD”重要信息为T、TD,T代表颗粒版本我这个就是T-DI…

  • 如何获取相应tableview中的touchesBegan事件[通俗易懂]

    如何获取相应tableview中的touchesBegan事件[通俗易懂]我

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号