Mutex 实现互斥
在并发编程中,保护共享资源不被多个线程同时修改是核心问题。Mutex(互斥体)提供了一种机制,确保同一时刻只有一个线程能持有该锁。
基本用法
调用 WaitOne() 方法会尝试获取互斥体的访问权。如果当前没有其他线程持有,则立即返回;否则当前线程会被挂起,直到锁被释放。一旦获取成功,必须在使用完资源后调用 ReleaseMutex() 归还锁。
bool createdNew;
var mutex = new Mutex(false, "MyMutex", out createdNew);
在构造函数中,我们可以指定互斥体是否由调用线程初始拥有,并定义一个全局名称。关键点在于:命名的互斥体可以在不同进程间共享,因为操作系统维护着这个名称的映射。未命名的互斥体仅限于当前进程内的线程同步。
单实例应用模式
利用系统级命名互斥体,可以方便地限制应用程序只能运行一个实例。如果检测到互斥体已存在(即 createdNew 为 false),则说明已有其他实例在运行。
[STAThread]
static void Main()
{
bool createdNew;
var mutex = new Mutex(false, "MyUniqueAppMutex", out createdNew);
if (!createdNew)
{
MessageBox.Show("您只能启动一个实例");
Application.Exit();
return;
}
// 主程序逻辑...
}
异常处理与安全性
获取锁后,务必使用 try-finally 块来确保锁被释放。如果在临界区发生异常,finally 中的 ReleaseMutex 依然会执行,避免死锁。
if (mutex.WaitOne())
{
try
{
// 受保护的代码
}
finally
{
mutex.ReleaseMutex();
}
}
else
{
// 获取失败的处理逻辑
}
Semaphore 计数信号量
如果说 Mutex 是'非此即彼'的开关,那么 Semaphore(信号量)就是一个计数器。它允许同时访问资源的线程数量达到设定值。

