Mutex 是 .NET 中用于线程同步和进程同步的一种工具。它的主要作用是确保在某一时刻只有一个线程或进程可以访问某个共享资源。下面是关于 Mutex 的详细介绍:
1. Mutex 的基本概念
Mutex(互斥锁)是一种同步原语,用于在多线程或多进程环境中,确保同一时间只有一个线程或进程访问特定的代码段或共享资源。它的主要目的是避免竞争条件,防止多个线程或进程同时操作共享资源,导致数据不一致或程序崩溃。
2. Mutex 的用途
线程同步:在单个进程内,当多个线程尝试访问共享资源时,可以使用 Mutex 来同步这些线程,避免数据冲突。
进程同步:不同进程中的线程如果要共享资源,也可以使用 Mutex 来确保同一时间只有一个进程在访问该资源。
3. 创建和获取 Mutex
创建和获取一个 Mutex 的常见方式:
Mutex mutex = new Mutex(); // 创建一个未被拥有的互斥锁
使用命名 Mutex(跨进程同步):
Mutex mutex = new Mutex(true, "MyMutexName", out bool acquired);
true:表示程序在创建时就尝试获取锁(初始所有者)。
"MyMutexName":这是互斥锁的名称。这个名称是唯一的,跨进程共享。如果其他进程使用相同的名称,就表示它们在访问相同的互斥锁。
out bool acquired:这个 out 参数表示当前进程是否成功获取到了互斥锁。acquired 为 true 表示成功获得锁,false 表示无法获得锁。
获取锁:mutex.WaitOne(); // 获取锁,直到成功
WaitOne:这个方法会使当前线程等待,直到它能够成功获取到互斥锁。如果锁已经被其他线程或进程持有,当前线程将阻塞,直到锁被释放。
释放锁:mutex.ReleaseMutex(); // 释放锁
ReleaseMutex():当一个线程或者进程完成对共享资源的操作后,需要调用 ReleaseMutex 来释放锁。这样,其他线程或进程就可以获取该锁,继续访问共享资源。
4. Mutex 的工作原理
同一进程中的线程:
独占性:一个 Mutex 对象在同一时刻只能被一个线程持有。如果一个线程已经持有了互斥锁,其他线程必须等待,直到持有锁的线程释放它。
跨进程的互斥:
跨进程共享:当 Mutex 使用名称时,多个进程可以通过相同的名称来访问同一个互斥锁。这允许跨进程的同步,确保不同进程不会同时访问同一个共享资源。
5. 常见方法和属性
Mutex.WaitOne():用来请求并获取互斥锁。如果锁已经被占用,当前线程会被阻塞,直到锁可用。
Mutex.ReleaseMutex():用来释放锁。只有持有锁的线程才可以调用此方法释放锁,其他线程不能调用。
Mutex.WaitOne(int millisecondsTimeout):尝试获取锁,如果锁在指定的时间内没有被占用,它就会成功获取锁。如果时间过期,返回 false。
Mutex.WaitOne(TimeSpan timeout):类似于上面的 millisecondsTimeout,但是使用 TimeSpan 来指定等待的时间。
Mutex.WaitOne(TimeSpan timeout, bool exitContext):除了指定超时时间外,还可以指定退出上下文(例如是否释放其他同步资源)。
Mutex.Dispose():销毁 Mutex 对象并释放它占用的资源。在不再需要 Mutex 时应调用此方法。
6. Mutex 与 Monitor 的区别
Mutex 和 Monitor 都可以用于同步线程,但它们有一些显著的区别:
Mutex可以用于线程同步,也可以用于进程同步;相对较慢,因为它支持进程间同步;不支持继承;当你需要跨进程同步时使用 Mutex。
Monitor仅用于线程同步;性能较高,只用于同一进程中的线程同步;支持继承;当你只需要线程间同步时使用 Monitor。
Mutex 是一种跨进程的同步机制,可以在不同进程之间进行同步。
Monitor 主要用于同一个进程中的线程同步,不支持跨进程同步。
7. 示例:互斥锁确保程序只有一个实例
假设我们希望确保某个程序只能有一个实例运行,可以使用命名的 Mutex 来实现:
class Program
{
  static Mutex mutex = new Mutex(true, "MyUniqueMutexName", out bool createdNew);
  static void Main()
  {
    if (!createdNew)
    {
      Console.WriteLine("The application is already running.");
      return;
    }
    Console.WriteLine("Application is running. Press any key to exit...");
    Console.ReadKey();
    mutex.ReleaseMutex();
  }
}
//方式2
//这里使用了Mutex的另一种构造方式,它会返回一个布尔值,指示是否成功创建了互斥体(即是否当前是第一个实例)。
//如果不是第一个实例,则显示消息并退出。注意这里的Global\\前缀是为了使互斥体在所有会话中都是全局的。
bool createdNew;
var mutex = new Mutex(true, "Global\\" + Application.ProductName, out createdNew);
if (!createdNew)
{
  MessageBox.Show("应用程序已经在运行!");
  return; // 退出程序
}
8. 注意事项
释放互斥锁:每次成功获取锁后,都必须确保释放锁,否则其他线程或进程将无法访问该资源,可能导致死锁。
死锁:如果两个线程持有相互依赖的锁并且都在等待对方释放锁,就会发生死锁。为了避免死锁,要谨慎设计锁的获取顺序。
跨进程使用:只有在互斥锁使用名称时,它才可以跨进程同步。普通的 Mutex 仅限于单个进程内部。
9. 总结
Mutex 是一种跨线程、跨进程的同步机制,确保同一时刻只有一个线程或进程访问共享资源。
它具有独占性,一个线程/进程在持有锁时,其他线程/进程无法访问该资源。
在多进程同步时,使用命名的 Mutex 对象,通过共享的名字来实现不同进程间的同步。
在使用 Mutex 时,要确保在使用完资源后正确释放锁,以避免死锁和资源浪费。
原文链接:https://blog.csdn.net/skvjw/article/details/144258403

posted on 2025-06-19 11:20  邢帅杰  阅读(152)  评论(0)    收藏  举报