C# 互斥锁
最后修改于 2023 年 7 月 5 日
在本文中,我们将展示如何使用 Mutex 原语来确保 C# 中的线程安全。
线程是程序的一个唯一执行路径。Thread 类表示 C# 中的一个线程。它创建和控制线程,设置其优先级并获取其状态。
当一组线程共享相同的资源,并且由于试图访问已被另一个线程锁定的资源而被彼此阻塞时,就会发生死锁。
互斥锁
为了确保线程安全,我们需要一种同步机制来授予对共享资源的访问权限。 互斥锁是一种同步原语,它仅授予一个线程访问共享资源的权限。 其他想要访问该资源的线程将被阻塞,直到持有互斥锁的线程释放它。
互斥锁类似于锁,但它可以跨多个进程工作; 也就是说,它可以是计算机范围的,也可以是应用程序范围的。 Mutex 类位于 System.Threading 命名空间中。
访问共享资源的代码部分称为临界区或保护区。 该资源可以是数据结构或设备。 线程使用 WaitOne 获取互斥锁,并使用 ReleaseMutex 释放互斥锁。
C# 互斥锁简单示例
以下是一个使用互斥锁的简单示例。
class Program
{
private static Mutex mutex = new Mutex();
private const int nThreads = 4;
private static void Worker()
{
UseResource();
}
private static void UseResource()
{
mutex.WaitOne();
string? name = Thread.CurrentThread.Name;
Console.WriteLine($"{name} has entered protected section");
Thread.Sleep(800);
Console.WriteLine($"{name} has left protected section");
mutex.ReleaseMutex();
}
static void Main(string[] args)
{
for (int i = 0; i < nThreads; i++)
{
var t = new Thread(new ThreadStart(Worker));
t.Name = $"Thread {i + 1}";
t.Start();
}
Console.Read();
}
}
在该程序中,我们创建了四个访问共享资源的线程。 每个线程都具有对资源的独占访问权限。
private static Mutex mutex = new Mutex();
Mutex 是一个静态字段。
private static void Worker()
{
UseResource();
}
每个线程都调用此 worker 函数。
private static void UseResource()
{
mutex.WaitOne();
string? name = Thread.CurrentThread.Name;
Console.WriteLine($"{name} has entered protected section");
Thread.Sleep(800);
Console.WriteLine($"{name} has left protected section");
mutex.ReleaseMutex();
}
这是代码的临界区,它使用 WaitOne 和 ReleaseMutex 方法通过互斥锁进行保护。
for (int i = 0; i < nThreads; i++)
{
var t = new Thread(new ThreadStart(Worker));
t.Name = $"Thread {i + 1}";
t.Start();
}
在一个 for 循环中,我们生成四个线程。
Console.Read();
为了确保所有线程都有时间完成,我们调用 Console.Read 方法。 只需在线程运行完成后按 Enter 键即可。
$ dotnet run Thread 1 has entered protected section Thread 1 has left protected section Thread 2 has entered protected section Thread 2 has left protected section Thread 3 has entered protected section Thread 3 has left protected section Thread 4 has entered protected section Thread 4 has left protected section
C# 互斥锁单实例
在以下示例中,我们创建一个单实例应用程序。 只允许在计算机上运行一个应用程序。
要创建单实例应用程序,我们使用命名互斥锁。 为了使互斥锁适用于所有终端会话,互斥锁的名称以 Global\ 为前缀。
public class Program
{
public static void Main()
{
using var mutex = new Mutex(false, @"Global\MySingletonApp");
bool IsRunning = !mutex.WaitOne(TimeSpan.Zero);
if (IsRunning)
{
Console.WriteLine("application is already running");
return;
}
Console.WriteLine("application started");
Console.ReadKey();
mutex.ReleaseMutex();
}
}
在该程序中,我们创建了一个全局命名互斥锁。 这可以防止我们在计算机上创建多个应用程序实例。 只有在正在运行的应用程序完成后才能运行该程序的另一个实例。
尝试在两个不同的终端中运行该应用程序。
来源
在本文中,我们使用了 Mutex 原语来同步 C# 中对受保护资源的访问。
作者
列出所有 C# 教程。