当前位置:首页 > Web开发 > 正文

.NET 中使用 Mutex 进行跨越进程边界的同步

2024-03-31 Web开发

标签:

原文:.NET 中使用 Mutex 进行跨越进程边界的同步

Mutex 是 Mutual Exclusion 的缩写,是互斥锁,用于防止两个线程同时对计算机上的同一个资源进行访问。不过相比于其他互斥的方式,Mutex 能够跨越线程边界。

本文内容

Mutex 是什么?

与其他线程同步的方式一样,Mutex 也提供对资源的互斥访问;不过 Mutex 使用的系统资源会比 Monitor 更多,而 Monitor 就是实现 C# 中 lock 关键字所用的锁。

用更多的系统资源,带来更强大的功能 —— Mutex 能进行跨越应用程序域边界的封送,能进行跨越进程边界的线程同步。

简单的 Mutex(不能跨进程互斥)

最简单的 Mutex 的使用方法就是直接 new 出来,然后使用 Wait 进行等待,使用 ReleaseMutex 进行释放。

private readonly Mutex _mutex = new Mutex(); private void UseResource() { _mutex.WaitOne(); // 等待一小段时间,假装正在使用公共资源。这里的一段代码在单个进程之内将无法重入。 Thread.Sleep(500); _mutex.ReleaseMutex(); }

1

2

3

4

5

6

7

8

9

10

11

参数中有一个 initiallyOwned 参数,如果指定为 true 表示创建这个 Mutex 的线程拥有这个资源(不需要等待),当这个线程调用 ReleaseMutex 之后其他线程的 WaitOne 才会生效。

不过这种方式不能达到跨进程同步的效果,,所以实际上本文并不会过多描述这种互斥方式。

创建跨进程互斥的 Mutex

要创建跨进程互斥的 Mutex,必须要给 Mutex 指定名称。

使用 new Mutex(false, "Walterlv.Mutex") 创建一个命名的互斥锁,以便进行跨进程的资源互斥访问。

在使用这个构造函数重载的时候,第一个参数 initiallyOwned 建议的取值为 false。因为当你指定为 true 时,说明你希望此线程是初始创建此 Mutex 的线程,然而由于你是直接 new 出来的,所以你实质上是无法得知你到底是不是第一个 new 出来的。

class Program { static async Task Main(string[] args) { var program = new Program(); while (true) { // 不断地尝试访问一段资源。这样,当多个进程运行的时候,可以很大概率模拟出现资源访问冲突。 program.UseResource(); await Task.Delay(50); } } private void UseResource() { var mutex = new Mutex(false, "Walterlv.Mutex"); mutex.WaitOne(); // 正在使用公共资源。 // 这里的一段代码将无法重入,即使是两个不同的进程。 var path = @"C:\Users\lvyi\Desktop\walterlv.log"; Console.WriteLine($"[{DateTime.Now:O}] 开始写入文件……"); File.AppendAllText(path, $"[{DateTime.Now:O}] 开始写入文件……", Encoding.UTF8); Thread.Sleep(1000); File.AppendAllText(path, $"[{DateTime.Now:O}] 写入文件完成。", Encoding.UTF8); Console.WriteLine($"[{DateTime.Now:O}] 写入文件完成。"); mutex.ReleaseMutex(); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/40146.html