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 方法来释放互斥体的所有权。 示例部分中的第一个示例演示了此模式。调用具有
millisecondsTimeout
或timeout
参数的方法中指定的WaitOne超时间隔已过。 发生这种情况时, WaitOne 方法返回false
,调用线程不会进一步尝试获取互斥体的所有权。 在这种情况下,应构建代码,以便拒绝对调用线程访问受互斥体保护的资源。 由于线程从未获取互斥体的所有权,因此它不得调用 ReleaseMutex 方法。 示例部分中的第二个示例演示了此模式。
类 Mutex 强制实施线程标识,因此只能由获取它的线程释放互斥体。 相比之下, Semaphore 类不强制实施线程标识。 互斥体也可以跨应用程序域边界传递。
拥有互斥体的线程可以在重复调用 WaitOne 中请求相同的互斥,而不会阻止其执行。 但是,线程必须调用 ReleaseMutex 方法的次数相同,才能释放互斥体的所有权。
Mutex由于 类继承自 WaitHandle,因此还可以调用静态 WaitHandle.WaitAll 和 WaitHandle.WaitAny 方法来同步对受保护资源的访问。
如果线程在拥有互斥体时终止,则表示该互斥体将被放弃。 互斥体的状态设置为已发出信号,下一个等待线程获取所有权。 从 .NET Framework 2.0 版开始,在下一个AbandonedMutexException获取已放弃的互斥体的线程中会引发 。 在 2.0 版.NET Framework之前,未引发异常。
注意
放弃的互斥通常表示代码中存在严重错误。 当线程退出而不释放互斥体时,受互斥体保护的数据结构可能处于不一致状态。 如果可以验证数据结构的完整性,则请求互斥锁所有权的下一个线程可以处理此异常并继续。
对于系统范围的 mutex,放弃的 mutex 可能指示应用程序已突然终止(例如,通过使用 Windows 任务管理器终止)。
互斥体有两种类型:未命名的本地互斥体和命名系统互斥体。 本地 mutex 仅存在于进程中。 它可由进程中的任何线程使用,这些线程引用了 Mutex 表示互斥体的 对象。 每个未命名 Mutex 的对象都表示一个单独的本地互斥体。
命名的系统互斥体在整个操作系统中可见,可用于同步进程的活动。 可以使用接受名称的构造函数创建 Mutex 表示命名系统互斥体的对象。 操作系统对象可以同时创建,也可以在创建 Mutex 对象之前存在。 可以创建多个表示同一命名系统 mutex 的 Mutex 对象,还能使用 OpenExisting 方法打开现有的命名系统 mutex。
注意
在运行终端服务的服务器上,命名系统互斥体可以具有两个级别的可见性。 如果其名称以前缀 Global\
开头,则互斥体在所有终端服务器会话中可见。 如果互斥体的名称以前缀 Local\
开头,则互斥体仅在创建它的终端服务器会话中可见。 在这种情况下,服务器上的每个其他终端服务器会话中可以存在具有相同名称的单独互斥体。 如果在创建命名互斥体时未指定前缀,则它采用前缀 Local\
。 在终端服务器会话中,名称仅因前缀而不同的两个互斥体是单独的互斥体,并且两者对终端服务器会话中的所有进程都可见。 也就是说,前缀名称和Global\
Local\
描述互斥体名称的范围相对于终端服务器会话,而不是相对于进程。
注意
默认情况下,命名互斥体不限于创建它的用户。 其他用户可能能够打开和使用互斥体,包括通过输入互斥体而不退出互斥来干扰互斥体。 在类似 Unix 的操作系统上,文件系统用于实现命名互斥体,其他用户可能能够以更重要的方式干扰命名互斥体。 在 Windows 上,若要限制对特定用户的访问,可以使用构造函数重载或在 MutexAcl 创建命名互斥体时传入 MutexSecurity 。 在类似于 Unix 的操作系统上,目前无法限制对命名互斥体的访问。 避免在可能有不受信任的用户运行代码的系统上使用没有访问限制的命名互斥体。
反斜杠 (\) 是互斥体名称中的保留字符。 请勿在互斥名称中使用反斜杠 (\) ,除非在终端服务器会话中使用互斥体的说明中所述。 否则,即使互斥体的名称表示现有文件,也可能引发 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) |
设置本机操作系统等待句柄的安全句柄。 |
适用于
线程安全性
此类型是线程安全的。