前言
在并发编程中,确保共享资源的同步访问对防止数据损坏和保持数据一致性至关重要。互斥锁(Mutex)是一种用于同步线程访问共享资源的机制。互斥锁确保共享资源在同一时间点,只有一个线程可以访问,从而防止资源竞争与冲突。本文了解C#中Mutex实现互斥体的功能。
Mutex
Mutex 是一种同步的原语,在实现线程共享资源同步访问,防止数据损坏和保持数据一致性方面起着至关重要的作用。
1、关键概念
拥有权:在任何给定时间内,只有一个线程可以拥有互斥锁。拥有互斥锁的线程,负责在使用受保护资源完成后释放互斥锁。
互斥状态:互斥锁有二种状态,分别是处于有信号 (解锁) 或非有信号 (锁定) 状态。尝试获取锁定互斥锁的线程将被阻止,直到它可用。
Mutex 的基本操作包括创建、获取、释放几个基本操作。
在 C# 中,可以使用 System.Threading 命名空间的 Mutex 类创建 Mutex 对象。
// 创建一个具默认属性的Mutex 实例 【未命名且初始所有权未获取】
Mutex mutex = new Mutex();
// 创建一个命名为GlobalMutexName,但初始所有权未获取的 Mutex实例
Mutex mutex = new Mutex(false, "Global_MutexName");
通过使用类提供的 WaitOne 方法获取互斥锁。
// 获取 Mutex
mutex.WaitOne();
try
{
// 访问共享资源
}
finally
{
mutex.ReleaseMutex();
}
通过使用类提供的 ReleaseMutex 方法释放互斥锁。
// 获取Mutex
mutex.WaitOne();
try
{
// 访问共享资源
}
finally
{
//释放
mutex.ReleaseMutex();
}
2.4、为互斥锁命名
在创建 Mutex 时可以指定互斥锁名称,通过互斥锁名称可以在不同的进程之间共享同一个 Mutex 实例。在跨进程同步的应用场景中互斥锁名称非常有用。
bool createdMutex;
using (Mutex mutex = new Mutex(false, "Global_MutexName", out createdNew))
{
if (!createdMutex)
{
Console.WriteLine("Mutex 已存在,可能已有另一个实例在运行。");
}
// 请求获取 Mutex
mutex.WaitOne();
try
{
// 访问共享资源
}
finally
{
// 释放 Mutex
mutex.ReleaseMutex();
}
}
参考命名
建议使用 Global_ 前缀表示全局、Local_ 前缀表示当前,通过命名前缀以明确 Mutex 的作用范围。
2.5、使用具有超时的互斥锁(Mutex)
我们可以在尝试获取互斥锁时指定超时,以避免无限期阻塞。if (mutex.WaitOne(TimeSpan.FromSeconds(8)))
{
try
{
// 访问共享资源
}
finally
{
mutex.ReleaseMutex();
}
}
else
{
// 处理超时情况
}
3、注意事项
确保 Mutex 对象释放:可使用 try...finally 语句块在访问结束后确保释放 Mutex,避免死锁;
避免长时间持有 Mutex:尽量缩短持有 Mutex 的时间,减少线程等待时间,提高性能;
做好异常处理:由于在获取或释放 Mutex 时可能会抛出异常,所以需做好异常处理;
避免互斥锁名称重复:互斥锁名命名时,应确保其唯一性,避免与其他应用程序的 Mutex 冲突;
示例
1、在多线程应用程序中写入文件
namespace Fountain.WinConsole.MutexDemo
{
internal class Program
{
private static Mutex fileMutex = new Mutex();
/// <summary>
/// 程序入口
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
// 启动多个线程
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(WriteToFile));
thread.Name = $"线程-{i + 1}";
thread.Start("写入文件的内容");
}
Console.ReadKey();
}
/// <summary>
/// 写入文件
/// </summary>
/// <param name="writeContent"></param>
public static void WriteToFile(object writeContent)
{
// 获取互斥锁时指定超时
if (fileMutex.WaitOne(TimeSpan.FromSeconds(8)))
{
try
{
Console.WriteLine($"{Thread.CurrentThread.Name} 获得 Mutex。正在访问共享资源...");
Thread.Sleep(400);
Console.WriteLine($"{Thread.CurrentThread.Name} 访问完毕。");
}
finally
{
fileMutex.ReleaseMutex();
Console.WriteLine($"{Thread.CurrentThread.Name} 释放了 Mutex。");
}
}
else
{
Console.WriteLine($"{Thread.CurrentThread.Name} 处理超时情况。");
}
}
}
}
小结
Mutex 可以有效避免同步线程数据竞争和资源冲突,提高应用程序的稳定性和可靠性。通过了解 Mutex,并通过正确使用Mutex,才能有效地管理并发访问,确保程序的正确性和稳定性。希望本文能给您带来帮助,如有不到之处,请多多包涵。
该文章在 2024/11/4 10:28:01 编辑过