Mutex 类

Mutex 中文为互斥,Mutex 类叫做互斥锁。它还可用于进程间同步的同步基元。

Mutex 跟 lock 相似,但是 Mutex 支持多个进程。Mutex 大约比 lock 慢 20 倍。

互斥锁(Mutex),用于多线程中防止两条线程同时对一个公共资源进行读写的机制。

Windows 操作系统中,Mutex 同步对象有两个状态:

  • signaled:未被任何对象拥有;
  • nonsignaled:被一个线程拥有;

Mutex 只能在获得锁的线程中,释放锁。

构造函数和方法

Mutex 类其构造函数如下:

Mutex 对于进程同步有所帮助,例如其应用场景主要是控制系统只能运行一个此程序的实例。

Mutex 构造函数中的 String类型参数 叫做互斥量而互斥量是全局的操作系统对象。

Mutex 只要考虑实现进程间的同步,它会耗费比较多的资源,进程内请考虑 Monitor/lock。

Mutex 的常用方法如下:

关于 Mutex 类,我们可以先通过几个示例去了解它。

系统只能运行一个程序的实例

下面是一个示例,用于控制系统只能运行一个此程序的实例,不允许同时启动多次。

class 

上面的代码中,有些地方前面没有讲,没关系,我们运行一下生成的程序先。

解释一下上面的示例

Mutex 的工作原理:

当两个或两个以上的线程同时访问共享资源时,操作系统需要一个同步机制来确保每次只有一个线程使用资源。

Mutex 是一种同步基元,Mutex 仅向一个线程授予独占访问共享资源的权限。这个权限依据就是 互斥体,当一个线程获取到互斥体后,其它线程也在试图获取互斥体时,就会被挂起(阻塞),直到第一个线程释放互斥体。

对应我们上一个代码示例中,实例化 Mutex 类的构造函数如下:

new Mutex(

其构造函数原型如下:

public Mutex (bool initiallyOwned, string name, out bool createdNew);

前面我们提出过,Mutex 对象有两种状态,signalednonsignaled

通过 new 来实例化 Mutex 类,会检查系统中此互斥量 name 是否已经被使用,如果没有被使用,则会创建 name 互斥量并且此线程拥有此互斥量的使用权;此时 createdNew == true

那么 initiallyOwned ,它的作用是是否允许线程是否能够获取到此互斥量的初始化所有权。因为我们希望只有一个程序能够在后台运行,因此我们要设置为 false。

驱动开发中关于 Mutex :https://docs.microsoft.com/zh-cn/windows-hardware/drivers/kernel/introduction-to-mutex-objects

对了, Mutex 的 参数中,name 是非常有讲究的。

在运行终端服务的服务器上,命名系统 mutex 可以有两个级别的可见性。

  • 如果其名称以前缀 "Global" 开头,则 mutex 在所有终端服务器会话中可见。
  • 如果其名称以前缀 "Local" 开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,可以在服务器上的其他每个终端服务器会话中存在具有相同名称的单独 mutex。
  • 如果在创建已命名的 mutex 时未指定前缀,则采用前缀 "Local"。在终端服务器会话中,两个互斥体的名称只是它们的前缀不同,它们都是对终端服务器会话中的所有进程都可见。

也就是说,前缀名称 "Global" 和 "Local" 描述互斥体名称相对于终端服务器会话的作用域,而不是相对于进程。

请参考:

  • https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.mutex?view=netcore-3.1#methods
  • https://www.cnblogs.com/suntp/p/8258488.html

接替运行

这里要实现,当同时点击一个程序时,只能有一个实例A可以运行,其它实例进入等待队列,等待A运行完毕后,然后继续运行队列中的下一个实例。

我们将每个程序比作一个人,模拟一个厕所坑位,每次只能有一个人上厕所,其他人需要排队等候。

使用 WaitOne() 方法来等待别的进程释放互斥量,即模拟排队;ReleaseMutex() 方法解除对坑位的占用。

class 

此时,我们使用了

new Mutex(

一个程序结束后,要允许其它线程能够创建 Mutex 对象获取互斥量,需要将构造函数的第一个参数设置为 true

你也可以改成 false,看看会报什么异常。

你可以使用 WaitOne(Int32) 来设置等待时间,单位是毫秒,超过这个时间就不排队了,去别的地方上厕所。

为了避免出现问题,请考虑在 finally 块中执行 m.ReleaseMutex()

进程同步示例

这里我们实现一个这样的场景:

父进程 Parent 启动子进程 Children ,等待子进程 Children 执行完毕,子进程退出,父进程退出。

新建一个 .NET Core 控制台项目,名称为 Children,其 Progarm 中的代码如下

using System;

然后发布或生成项目,打开程序文件位置,复制线程文件路径。

创建一个新项目,名为 Parent 的 .NET Core 控制台,其 Program 中的代码如下:

using System;

请将 Children 项目的程序文件路径,替换到 Parent 项目启动子进程的那部分字符串中。

然后启动 Parent.exe,可以观察到如下图的运行过程:

另外

构造函数中,如果为 name 指定 null 或空字符串,则将创建一个本地 Mutex 对象,只会在进程内有效。

Mutex 有些使用方法比较隐晦,可以参考:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.mutex.-ctor?view=netcore-3.1#System_Threading_Mutex__ctor_System_Boolean_

另外打开互斥体,请参考:

  • https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.mutex.openexisting?view=netcore-3.1
  • https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.mutex.tryopenexisting?view=netcore-3.1

到目前为止,我们学习了排他锁 lock、Monitor、Mutex。下一篇我们将来学习非排他锁定结构的 SemaphoreSemaphoreSlim

﹏﹏﹏﹏

在c#中用mutex类实现线程的互斥_C# 多线程系列(4)进程同步Mutex类相关推荐

  1. 线程互斥与同步 在c#中用mutex类实现线程的互斥_Golang 并发编程与同步原语

    5.1 同步原语与锁 · 浅谈 Go 语言实现原理​draveness.me 当提到并发编程.多线程编程时,我们往往都离不开『锁』这一概念,Go 语言作为一个原生支持用户态进程 Goroutine 的 ...

  2. java线程如何继承,java多线程(一)之继承Thread类

    一.概述 进程:正在执行的应用程序 线程:进程的执行单元,执行路径 单线程:一个应用程序只有一条执行路径 多线程:一个应用程序有多条执行路径 二.两种实现方式, 下面为第一种方式: 继承Thread类 ...

  3. java判断线程是否死锁_c++多线程锁 Mutex  自动判断死锁

    c++多线程锁可以使用absl::Mutex  std::mutex这两种,下面是demo代码. 使用absl:Mutex的时候打印: [mutex.cc : 1338] RAW: Cycle: [m ...

  4. vb.net 线程偶尔不会自动关闭_C# 多线程系列(7)手动线程通知

    区别与示例 AutoResetEvent 和 ManualResetEvent 十分相似.两者之间的区别,在于前者是自动(Auto),后者是手动(Manua). 你可以先运行下面的示例,再测试两者的区 ...

  5. 在c#中用mutex类实现线程的互斥_面试官经常问的synchronized实现原理和锁升级过程,你真的了解吗...

    本篇文章主要从字节码和JVM底层来分析synchronized实现原理和锁升级过程,其中涉及到了简单认识字节码.对象内部结构以及ObjectMonitor等知识点. 阅读本文之前,如果大家对synch ...

  6. 基类指针调用派生类函数_C++ 多态性:虚函数--基类与派生类类型转换(第7章 05)例子问题解析(学习笔记:第8章 05)...

    虚函数[1] 问题:还记得第7章的例子吗[2]? 例7-3 类型转换规则举例 #include <iostream> using namespace std; class Base1 { ...

  7. java线程创建销毁_c++多线程的创建挂起执行与销毁

    资源简介 1. 创建一个基于对话框的应用程序.并增加如图所示控件:分别为3个进度条控件关联三个进度条类型的变量:并在对话框的初始化函数中,设定进度条的范围:为编辑框关联一个整型的变量:为12个按钮添加 ...

  8. 求python一个类与对象的代码_Python基础系列(五)类和对象,让你更懂你的python代码...

    首先,非常感谢各位打开本博文,本博文是Python入门基础系列文章之一,Python目前是非常火的编程工具,其实作为编程不在只是程序员的专利,每一个人在日常的工作中.学习中都会或多或少的要用到一些工具 ...

  9. Java多线程系列(二):线程的五大状态,以及线程之间的通信与协作

    在Java面试的时候,经常会问到Java并发编程相关的多线程.线程池.线程锁.线程通信等面试必考点,比如: Java并发编程系列:Java线程池的使用方式,核心运行原理.以及注意事项 Java并发编程 ...

最新文章

  1. 【转】使用Apache Kylin搭建企业级开源大数据分析平台
  2. 一个超强的逆向分析软件
  3. 关于-最佳的业务连续性容灾架构设计
  4. 懒人分析jQuery源码
  5. 2.7 矩阵分块及矩阵乘法的四种方式
  6. sql sever还原失败:无法覆盖文件,数据库 'XX' 正在使用该文件”的问题
  7. 软件测试-正交实验法设计测试用例
  8. 小米最新系统android 10,国内最快推送安卓10稳定版系统!小米新旗舰出厂标配稳了...
  9. 正斜杠 ,又称左斜杠,符号是/;反斜杠,也称右斜杠,符号是\。
  10. python钻石和玻璃球游戏_python使用pygame实现笑脸乒乓球弹珠球游戏
  11. contiki学习笔记(四)、contiki系统UDP通信原理(单播、多播、RPL介绍)
  12. Smart Construction:工程机械正在加速进入智能建设时代
  13. 计算机c语言二级编程题题库,计算机等级考试二级c语言编程题题库
  14. Android截取人物头像,Android 图片截取人物头像(仿逗拍)
  15. hdu 5148 树形dp,分组背包
  16. 再谈java内存模型
  17. LightSwitch 社区内容汇总 – 2012年9月
  18. Linux 指令:怎样从文件中找到重复行?
  19. PyQt5 TableView组件
  20. echarts python 教程_Echarts入门(零基础小白教程)

热门文章

  1. chrome插件分享
  2. Java程序猿面试体会,还没找到工作的“猿猿们”看过来!
  3. 利用mongodb开发lbs应用实践【转】
  4. ActiveRecord 模式杂谈
  5. 一个合格程序员的标准
  6. Mysql 数据库导入导出
  7. Notepad++ 使用心得
  8. 字符串在编号查询中的应用示例及常见问题.sql
  9. Python常用小技巧(二)——打开图片
  10. android parcel空指针,android - intent.hasExtra(“ meta”)抛出错误的可包裹异常 - 堆栈内存溢出...