“mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量。
当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
可以使用 WaitHandle.WaitOne 方法请求互斥体的所属权。拥有互斥体的线程可以在对 WaitOne 的重复调用中请求相同的互斥体而不会阻止其执行。但线程必须调用 ReleaseMutex 方法同样多的次数以释放互斥体的所属权。
在运行终端服务的服务器上,已命名的系统 mutex 可以具有两级可见性。如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。在这种情况下,服务器上各个其他终端服务器会话中都可以拥有一个名称相同的独立 mutex。如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。在终端服务器会话中,只是名称前缀不同的两个 mutex 是独立的 mutex,这两个 mutex 对于终端服务器会话中的所有进程均为可见。即:前缀名称“Global\”和“Local\”说明 mutex 名称相对于终端服务器会话(而并非相对于进程)的范围。
简单示例:
static class Program {
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
bool CreateNew;
System.Threading.Mutex mutex = new System.Threading.Mutex(false, "Application.ProjectName", out CreateNew);
if (!CreateNew)
{
System.Windows.Forms.MessageBox.Show("系统已运行,不用重复运行!");
Application.Exit();
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
}
}
下面的代码来自https://msdn.microsoft.com/zh-cn/library/system.threading.mutex.aspx
此示例演示如何使用局部 Mutex 对象来同步对受保护资源的访问。
// This example shows how a Mutex is used to synchronize access
// to a protected resource. Unlike Monitor, Mutex can be used with
// WaitHandle.WaitAll and WaitAny, and can be passed across
// AppDomain boundaries.
using System;
using System.Threading;
class Test
{
// Create a new Mutex. The creating thread does not own the
// Mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void MyThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area\r\n",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
}
}