Mutex 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
还可用于进程间同步的同步基元。
public ref class Mutex sealed : System::Threading::WaitHandle
public sealed class Mutex : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Mutex : System.Threading.WaitHandle
type Mutex = class
inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(true)>]
type Mutex = class
inherit WaitHandle
Public NotInheritable Class Mutex
Inherits WaitHandle
- 继承
- 继承
- 属性
示例
此示例演示如何使用本地 Mutex 对象同步对受保护资源的访问。 由于每个调用线程被阻止,直到它获取互斥体的所有权,因此它必须调用 ReleaseMutex 方法来释放互斥体的所有权。
using System;
using System.Threading;
class Example
{
// 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 newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
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.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name);
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",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread2 is requesting the mutex
// Thread1 has entered the protected area
// Thread3 is requesting the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
// Thread3 has entered the protected area
// Thread3 is leaving the protected area
// Thread3 has released the mutex
// Thread2 has entered the protected area
// Thread2 is leaving the protected area
// Thread2 has released the mutex
Imports System.Threading
Module Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Sub Main()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
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",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
End Sub
End Module
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread2 is requesting the mutex
' Thread1 has entered the protected area
' Thread3 is requesting the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
' Thread3 has entered the protected area
' Thread3 is leaving the protected area
' Thread3 has released the mutex
' Thread2 has entered the protected area
' Thread2 is leaving the protected area
' Thread2 has released the mutex
在下面的示例中,每个线程都调用 WaitOne(Int32) 该方法来获取互斥体。 如果超时间隔过,该方法将 false
返回,并且线程既不获取互斥体,也不获取互斥体保护的资源的访问权限。 该方法 ReleaseMutex 仅由获取互斥体的线程调用。
using System;
using System.Threading;
class Example
{
// 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()
{
Example ex = new Example();
ex.StartThreads();
}
private void StartThreads()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread returns to Main and exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
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, and do not enter if the request times out.
Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
if (mut.WaitOne(1000)) {
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(5000);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
else {
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name);
}
}
~Example()
{
mut.Dispose();
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread1 has entered the protected area
// Thread2 is requesting the mutex
// Thread3 is requesting the mutex
// Thread2 will not acquire the mutex
// Thread3 will not acquire the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
Imports System.Threading
Class Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Shared Sub Main()
Dim ex As New Example()
ex.StartThreads()
End Sub
Private Sub StartThreads()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread returns to Main and exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
If mut.WaitOne(1000) Then
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name)
' Place code to access non-reentrant resources here.
' Simulate some work.
Thread.Sleep(5000)
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
Else
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name)
End If
End Sub
Protected Overrides Sub Finalize()
mut.Dispose()
End Sub
End Class
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread1 has entered the protected area
' Thread2 is requesting the mutex
' Thread3 is requesting the mutex
' Thread2 will not acquire the mutex
' Thread3 will not acquire the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
注解
当两个或多个线程需要同时访问共享资源时,系统需要同步机制来确保一次只有一个线程使用资源。 Mutex 是一个同步基元,仅向一个线程授予对共享资源的独占访问权限。 如果线程获取互斥体,则要获取互斥体的第二个线程将暂停,直到第一个线程释放互斥体。
重要
此类型实现 IDisposable 接口。 在使用完类型后,您应直接或间接释放类型。 若要直接释放类型,请在 try
/catch
块中调用其 Dispose 方法。 若要间接释放类型,请使用 using
(在 C# 中)或 Using
(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅 IDisposable 接口主题中的“使用实现 IDisposable 的对象”一节。
可以使用 WaitHandle.WaitOne 该方法请求互斥体的所有权。 调用线程会阻塞,直到发生以下情况之一:
向互斥体发出信号,指示它不拥有。 发生这种情况时,该方法 WaitOne 返回
true
,调用线程假定互斥体的所有权,并访问受互斥体保护的资源。 访问完资源后,线程必须调用 ReleaseMutex 该方法才能释放互斥体的所有权。 “示例”部分中的第一个示例说明了此模式。调用 WaitOne 具有
millisecondsTimeout
或timeout
参数的方法时指定的超时间隔。 发生这种情况时, WaitOne 该方法返回false
,调用线程不会进一步尝试获取互斥体的所有权。 在这种情况下,应构建代码,以便对受互斥体保护的资源的访问被拒绝到调用线程。 由于线程从未获取互斥体的所有权,因此它不得调用 ReleaseMutex 该方法。 “示例”部分中的第二个示例说明了此模式。
类 Mutex 强制实施线程标识,因此只能由获取它的线程释放互斥体。 相比之下,该 Semaphore 类不强制实施线程标识。 还可以跨应用程序域边界传递互斥体。
拥有互斥体的线程可以在重复调用 WaitOne 中请求相同的互斥体,而不会阻止其执行。 但是,线程必须调用 ReleaseMutex 相同次数的方法才能释放互斥体的所有权。
Mutex由于类继承自WaitHandle,因此还可以调用静态WaitHandle.WaitAll和WaitHandle.WaitAny方法来同步对受保护资源的访问。
如果线程在拥有互斥体时终止,则表示该互斥体将被放弃。 互斥体的状态设置为已发出信号,下一个等待线程获取所有权。 从.NET Framework版本 2.0 开始,在下一个获取废弃互斥体的线程中将引发一个AbandonedMutexException。 在.NET Framework版本 2.0 之前,不会引发异常。
注意
废弃的互斥体通常表示代码中出现严重错误。 当线程在不释放互斥体的情况下退出时,受互斥体保护的数据结构可能不处于一致状态。 如果可以验证数据结构的完整性,则请求互斥体所有权的下一个线程可以处理此异常并继续。
对于系统范围的 mutex,放弃的 mutex 可能指示应用程序已突然终止(例如,通过使用 Windows 任务管理器终止)。
互斥体分为两种类型:本地互斥体(未命名)和命名系统互斥体。 本地 mutex 仅存在于进程中。 它可由进程中具有对 Mutex 表示互斥体的对象引用的任何线程使用。 每个未命名 Mutex 的对象都表示单独的本地互斥体。
命名的系统互斥体在整个操作系统中可见,可用于同步进程的活动。 可以使用接受名称的构造函数创建一个 Mutex 对象,该对象代表命名的系统互斥体。 可以同时创建操作系统对象,也可以在创建 Mutex 对象之前存在该对象。 可以创建多个表示同一命名系统 mutex 的 Mutex 对象,还能使用 OpenExisting 方法打开现有的命名系统 mutex。
备注
在运行终端服务的服务器上,命名的系统互斥体可以具有两个级别的可见性。 如果名称以前缀“Global\”开头,则互斥体在所有终端服务器会话中可见。 如果名称以前缀“Local\”开头,则互斥体仅在创建它的终端服务器会话中可见。 在这种情况下,服务器上的其他每个终端服务器会话中都可以存在具有相同名称的单独互斥体。 如果在创建命名互斥体时未指定前缀,则它采用前缀“Local\”。 在终端服务器会话中,两个名称只与其前缀不同的互斥体是单独的互斥体,并且两者都对终端服务器会话中的所有进程可见。 也就是说,前缀名称“Global\”和“Local\”描述互斥体名称相对于终端服务器会话的范围,而不是相对于进程。
反斜杠 (\) 是互斥体名称中的保留字符。 请勿在互斥体名称中使用反斜杠 (\),除非在终端服务器会话中使用互斥体的注释中另有规定。 否则,即使互斥体的名称表示现有文件,也可能引发 DirectoryNotFoundException。
构造函数
Mutex() |
使用默认属性初始化 Mutex 类的新实例。 |
Mutex(Boolean) |
使用 Boolean 值(指示调用线程是否应具有互斥体的初始所有权)初始化 Mutex 类的新实例。 |
Mutex(Boolean, String) |
使用 Boolean 值(指示调用线程是否应具有互斥体的初始所有权以及字符串是否为互斥体的名称)初始化 Mutex 类的新实例。 |
Mutex(Boolean, String, Boolean) |
使用可指示调用线程是否应具有互斥体的初始所有权以及字符串是否为互斥体的名称的 Boolean 值和当线程返回时可指示调用线程是否已赋予互斥体的初始所有权的 Boolean 值初始化 Mutex 类的新实例。 |
Mutex(Boolean, String, Boolean, MutexSecurity) |
使用可指示调用线程是否应具有互斥体的初始所有权以及字符串是否为互斥体的名称的 Boolean 值和当线程返回时可指示调用线程是否已赋予互斥体的初始所有权以及访问控制安全是否已应用到命名互斥体的 Boolean 变量初始化 Mutex 类的新实例。 |
字段
WaitTimeout |
指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。 此字段为常数。 (继承自 WaitHandle) |
属性
Handle |
已过时。
已过时。
获取或设置本机操作系统句柄。 (继承自 WaitHandle) |
SafeWaitHandle |
获取或设置本机操作系统句柄。 (继承自 WaitHandle) |
方法
Close() |
释放由当前 WaitHandle 占用的所有资源。 (继承自 WaitHandle) |
CreateObjRef(Type) |
创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。 (继承自 MarshalByRefObject) |
Dispose() |
释放 WaitHandle 类的当前实例所使用的所有资源。 (继承自 WaitHandle) |
Dispose(Boolean) |
当在派生类中重写时,释放 WaitHandle 使用的非托管资源,并且可选择释放托管资源。 (继承自 WaitHandle) |
Equals(Object) |
确定指定对象是否等于当前对象。 (继承自 Object) |
GetAccessControl() |
获取表示已命名的互斥体的访问控制安全性的 MutexSecurity 对象。 |
GetHashCode() |
作为默认哈希函数。 (继承自 Object) |
GetLifetimeService() |
已过时。
检索控制此实例的生存期策略的当前生存期服务对象。 (继承自 MarshalByRefObject) |
GetType() |
获取当前实例的 Type。 (继承自 Object) |
InitializeLifetimeService() |
已过时。
获取生存期服务对象来控制此实例的生存期策略。 (继承自 MarshalByRefObject) |
MemberwiseClone() |
创建当前 Object 的浅表副本。 (继承自 Object) |
MemberwiseClone(Boolean) |
创建当前 MarshalByRefObject 对象的浅表副本。 (继承自 MarshalByRefObject) |
OpenExisting(String) |
打开指定的已命名的互斥体(如果已经存在)。 |
OpenExisting(String, MutexRights) |
用安全访问权限打开指定名称为 mutex(如果已经存在),并返回指示操作是否成功的值。 |
ReleaseMutex() |
释放 Mutex 一次。 |
SetAccessControl(MutexSecurity) |
设置已命名的系统互斥体的访问控制安全性。 |
ToString() |
返回表示当前对象的字符串。 (继承自 Object) |
TryOpenExisting(String, Mutex) |
打开指定的已命名的互斥体(如果已经存在),并返回指示操作是否成功的值。 |
TryOpenExisting(String, MutexRights, Mutex) |
利用所需的安全访问权限,打开指定的已命名的互斥体(如果已经存在),并返回指示操作是否成功的值。 |
WaitOne() |
阻止当前线程,直到当前 WaitHandle 收到信号。 (继承自 WaitHandle) |
WaitOne(Int32) |
阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。 (继承自 WaitHandle) |
WaitOne(Int32, Boolean) |
阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。 (继承自 WaitHandle) |
WaitOne(TimeSpan) |
阻止当前线程,直到当前实例收到信号,同时使用 TimeSpan 指定时间间隔。 (继承自 WaitHandle) |
WaitOne(TimeSpan, Boolean) |
阻止当前线程,直到当前实例收到信号为止,同时使用 TimeSpan 指定时间间隔,并指定是否在等待之前退出同步域。 (继承自 WaitHandle) |
显式接口实现
IDisposable.Dispose() |
此 API 支持产品基础结构,不能在代码中直接使用。 释放由 WaitHandle 使用的所有资源。 (继承自 WaitHandle) |
扩展方法
GetAccessControl(Mutex) |
返回指定的 |
SetAccessControl(Mutex, MutexSecurity) |
设置指定互斥体的安全描述符。 |
GetSafeWaitHandle(WaitHandle) |
获取本机操作系统等待句柄的安全句柄。 |
SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
设置本机操作系统等待句柄的安全句柄。 |
适用于
线程安全性
此类型是线程安全的。