编辑
2025-10-11
C#
00

目录

Mutex 的特点
使用 Mutex 的基本语法
示例:使用 Mutex 实现线程安全的计数器
示例:使用命名 Mutex 进行跨进程同步
示例:使用超时功能
示例:单实例应用程序
使用 Mutex 的注意事项
结论

在C#的多线程编程中,Mutex 是一种用于同步多个线程的机制。它不仅适用于进程间的线程同步,还可以在同一进程内用于保护共享资源。本文将详细介绍 Mutex 的特点、用法,并提供多个示例以示范其应用。

Mutex 的特点

  • 跨进程同步Mutex 允许在不同进程之间进行同步,这使得它在处理需要进程间通信的场景时相当有用。
  • 独占性访问:只有一个线程可以获得 Mutex,其他线程必须等待,直到该线程释放 Mutex
  • 超时控制Mutex 允许设置超时。如果线程在指定时间内无法获得锁,可以选择放弃。
  • 简单易用Mutex 提供了清晰的接口,易于程序员使用。

使用 Mutex 的基本语法

以下是 Mutex 的基本用法示例:

C#
Mutex mutex = new Mutex(); mutex.WaitOne(); //请求锁 // ... 访问共享资源 mutex.ReleaseMutex(); //释放锁

示例:使用 Mutex 实现线程安全的计数器

以下示例展示了如何使用 Mutex 来实现一个线程安全的计数器,确保只有一个线程可以对计数器进行更新。

C#
using System; using System.Threading; class Program { private static int counter = 0; // 共享资源 private static Mutex mutex = new Mutex(); // 创建 Mutex 实例 static void Main(string[] args) { Thread[] threads = new Thread[5]; for (int i = 0; i < threads.Length; i++) { threads[i] = new Thread(IncrementCounter); threads[i].Start(); } foreach (var thread in threads) { thread.Join(); } Console.WriteLine($"最终计数器的值: {counter}"); } static void IncrementCounter() { for (int i = 0; i < 1000; i++) { mutex.WaitOne(); // 请求锁 try { counter++; // 增加计数 } finally { mutex.ReleaseMutex(); // 确保释放锁 } } } }

image.png

示例:使用命名 Mutex 进行跨进程同步

当需要在不同进程中共享资源时,可以使用命名的 Mutex。以下示例展示了如何创建一个命名的 Mutex

C#
using System; using System.Threading; class Program { private static Mutex mutex; static void Main(string[] args) { string mutexName = "Global\\MyNamedMutex"; // 使用命名 mutex mutex = new Mutex(false, mutexName); // 创建一个命名的 mutex Thread thread1 = new Thread(AccessResource); Thread thread2 = new Thread(AccessResource); thread1.Start(); thread2.Start(); thread1.Join(); thread2.Join(); } static void AccessResource() { Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 正在请求锁..."); mutex.WaitOne(); // 请求锁 Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 获得了锁。"); // 模拟访问共享资源的操作 Thread.Sleep(2000); // 休眠2秒以模拟长时间的操作 Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 释放了锁。"); mutex.ReleaseMutex(); // 释放锁 } }

image.png

示例:使用超时功能

在某些情况下,锁请求可能会超时,以下示例展示了如何使用 Mutex 的超时功能。

C#
namespace AppMutex { internal class Program { private static Mutex mutex = new Mutex(); static void Main(string[] args) { Thread thread1 = new Thread(EnterCriticalSection); Thread thread2 = new Thread(EnterCriticalSection); thread1.Start(); thread2.Start(); thread1.Join(); thread2.Join(); } static void EnterCriticalSection() { Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 正在请求锁..."); if (mutex.WaitOne(1000)) { // 请求锁,最多等待1秒 try { Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 获得了锁。"); // 模拟长时间运行的操作 Thread.Sleep(3000); // 超过1秒的操作 } finally { mutex.ReleaseMutex(); Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 释放了锁。"); } } else { Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} 等待超时,未能获得锁。"); } } } }

image.png

  1. 超时请求:在获取 Mutex 锁时,设置了超时时间为1秒。
  2. 超时处理:如果在1秒内无法获得锁,则线程输出等待超时的信息。
  3. 将超时修改为4秒,可以正常释放了。

示例:单实例应用程序

C#
namespace AppMutex { internal class Program { static Mutex mutex = new Mutex(true, "MyAPPID"); static void Main(string[] args) { // 尝试获取互斥锁 if (mutex.WaitOne(TimeSpan.Zero, true)) { try { // 应用程序的主逻辑 Console.WriteLine("应用程序正在运行"); // 其他业务代码 } finally { // 释放互斥锁 mutex.ReleaseMutex(); } } else { Console.WriteLine("应用程序已经在运行"); return; } Console.ReadKey(); } } }

使用 Mutex 的注意事项

  • 确保释放锁:使用 try...finally 结构以确保 Mutex 始终被释放。
  • 性能影响:使用 Mutex 时要注意,它的创建、释放和等待都有一定的性能开销。
  • 避免过度竞争:多个线程频繁竞争同一个 Mutex 可能会导致性能下降。
  • 命名 Mutex 的唯一性:确保命名的 Mutex 在所有可能的进程中是唯一的,以防止冲突。

结论

Mutex 是C#中一种强大的多线程同步机制,尤其适合需要跨进程同步的场景。通过上述示例,您可以看到如何利用 Mutex 来确保共享资源的安全访问。尽管 Mutex 在多线程同步中的应用非常广泛,但使用时需关注性能和锁的管理,以避免潜在的死锁和竞争条件。合理地使用 Mutex 会显著提高多线程应用的稳定性和可靠性。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!