Mutex 类

定义

也可用于进程间同步的同步基元。

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 接口。 使用完该类型后,应直接或间接处理它。 若要直接释放类型,请在块中Disposetry/调用其catch方法。 若要间接释放它,请使用语言构造,例如 using (在 C# 中)或 Using (在 Visual Basic 中)。 有关详细信息,请参阅接口主题中的 IDisposable “使用实现 IDisposable 的对象”部分。

可以使用该方法 WaitHandle.WaitOne 请求互斥体的所有权。 调用线程会阻塞,直到发生以下情况之一:

  • 指示互斥体指示它不拥有。 发生这种情况时, WaitOne 该方法返回 true,调用线程假定互斥体的所有权并访问受互斥体保护的资源。 访问完资源后,线程必须调用 ReleaseMutex 该方法才能释放互斥体的所有权。 “示例”部分中的第一个示例说明了此模式。

  • 对具有WaitOnemillisecondsTimeout参数的方法的调用timeout中指定的超时间隔已经过去。 发生这种情况时, WaitOne 该方法返回 false,调用线程不会进一步尝试获取互斥体的所有权。 在这种情况下,应构建代码,以便对受互斥体保护的资源的访问被拒绝到调用线程。 由于线程从未获取互斥体的所有权,因此它不得调用该方法 ReleaseMutex 。 “示例”部分中的第二个示例说明了此模式。

Mutex 类强制实施线程标识,因此互斥体只能由获取它的线程释放。 相比之下,该 Semaphore 类不强制实施线程标识。 还可以跨应用程序域边界传递互斥体。

拥有互斥体的线程可以在重复调用 WaitOne 中请求相同的互斥体,而不会阻止其执行。 但是,线程必须调用 ReleaseMutex 相同次数的方法才能释放互斥体的所有权。

Mutex由于类继承自WaitHandle,因此还可以调用静态WaitHandle.WaitAllWaitHandle.WaitAny方法以同步对受保护资源的访问。

如果线程在拥有互斥体时终止,则表示将放弃互斥体。 互斥体的状态设置为信号,下一个等待线程获取所有权。 从 .NET Framework 版本 2.0 开始,AbandonedMutexException在获取放弃的互斥体的下一个线程中引发。 在 .NET Framework 版本 2.0 之前,不会引发异常。

注意

放弃的互斥体通常表示代码中出现严重错误。 当线程退出而不释放互斥体时,受互斥体保护的数据结构可能不处于一致状态。 如果可以验证数据结构的完整性,则请求互斥体所有权的下一个线程可以处理此异常并继续。

对于系统范围的 mutex,放弃的 mutex 可能指示应用程序已突然终止(例如,通过使用 Windows 任务管理器终止)。

互斥体分为两种类型:本地互斥体(未命名)和命名系统互斥体。 本地 mutex 仅存在于进程中。 它可由进程中具有对表示互斥体的对象引用 Mutex 的任何线程使用。 每个未命名 Mutex 对象都表示单独的本地互斥体。

命名系统互斥体在整个操作系统中可见,可用于同步进程的活动。 可以使用接受名称的构造函数创建一个 Mutex 对象,该对象表示命名的系统互斥体。 操作系统对象可以同时创建,也可以在创建 Mutex 对象之前存在。 可以创建表示同一命名系统互斥体的多个 Mutex 对象,并且可以使用 OpenExisting 该方法打开现有的命名系统互斥体。

Note

在运行终端服务的服务器上,命名的系统互斥体可以具有两个级别的可见性。 如果名称以前缀 Global\开头,则互斥体在所有终端服务器会话中可见。 如果名称以前缀 Local\开头,则互斥体仅在创建它的终端服务器会话中可见。 在这种情况下,服务器上其他终端服务器会话中可以存在同名的单独互斥体。 如果在创建命名互斥体时未指定前缀,则它采用前缀 Local\。 在终端服务器会话中,名称仅与其前缀不同的两个互斥体是单独的互斥体,并且两者都对终端服务器会话中的所有进程可见。 也就是说,前缀名称和Global\Local\描述互斥体名称相对于终端服务器会话的范围,而不是相对于进程。

注意

默认情况下,命名互斥体不限于创建它的用户。 其他用户可能能够打开和使用互斥体,包括通过输入互斥体而不是退出互斥体来干扰互斥体。 在类似 Unix 的操作系统上,文件系统用于命名互斥体的实现,其他用户可能能够以更重要的方式干扰命名互斥体。 在Windows,若要限制对特定用户的访问,可以使用构造函数重载或 MutexAcl,并在创建命名互斥体时传入 MutexSecurity。 在类似 Unix 的操作系统上,目前无法限制对命名互斥体的访问。 避免在可能具有不受信任的用户运行代码的系统上使用命名互斥体,而不受访问限制。

反斜杠 (\) 是互斥体名称中的保留字符。 请勿在互斥表达式名称中使用反斜杠(\),除非在终端服务器会话中使用互斥表达式的注释中指定。 否则, DirectoryNotFoundException 即使互斥体的名称表示现有文件,也可能引发 a。

构造函数

名称 说明
Mutex()

使用默认属性初始化类的新实例 Mutex

Mutex(Boolean, String, Boolean, MutexSecurity)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应拥有互斥体的初始所有权,字符串是互斥体的名称,一个布尔变量,该方法返回时,指示调用线程是否被授予互斥体的初始所有权,以及要应用于命名互斥体的访问控制安全性。

Mutex(Boolean, String, Boolean)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应具有互斥体的初始所有权、一个字符串(即互斥体的名称)和一个布尔值,该方法返回时,指示调用线程是否被授予互斥体的初始所有权。

Mutex(Boolean, String, NamedWaitHandleOptions, Boolean)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应拥有互斥体的初始所有权、一个字符串(即互斥体的名称、用于设置用户范围和会话范围访问的选项)以及一个布尔值,当该方法返回时,指示调用线程是否被授予互斥体的初始所有权。

Mutex(Boolean, String, NamedWaitHandleOptions)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应具有互斥体的初始所有权、互斥体的名称字符串以及设置用户范围和会话范围访问的选项。

Mutex(Boolean, String)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应具有互斥体的初始所有权,以及一个字符串,该字符串是互斥体的名称。

Mutex(Boolean)

使用布尔值初始化类的新实例 Mutex ,该值指示调用线程是否应具有互斥体的初始所有权。

Mutex(String, NamedWaitHandleOptions)

使用字符串初始化类的新实例 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, MutexRights)

使用所需的安全访问打开指定的命名互斥体(如果已存在)。

OpenExisting(String, NamedWaitHandleOptions)

打开指定的命名互斥体(如果已存在)。 如果选项仅设置为当前用户,则为调用用户验证对象的访问控制。

OpenExisting(String)

打开指定的命名互斥体(如果已存在)。

ReleaseMutex()

Mutex释放一次。

SetAccessControl(MutexSecurity)

设置命名系统互斥体的访问控制安全性。

ToString()

返回一个表示当前对象的字符串。

(继承自 Object)
TryOpenExisting(String, Mutex)

打开指定的命名互斥体(如果已存在),并返回一个值,该值指示操作是否成功。

TryOpenExisting(String, MutexRights, Mutex)

使用所需的安全访问打开指定的命名互斥体(如果已存在),并返回一个值,该值指示操作是否成功。

TryOpenExisting(String, NamedWaitHandleOptions, Mutex)

打开指定的命名互斥体(如果已存在),并返回一个值,该值指示操作是否成功。 如果选项仅设置为当前用户,则为调用用户验证对象的访问控制。

WaitOne()

阻止当前线程,直到当前 WaitHandle 接收信号。

(继承自 WaitHandle)
WaitOne(Int32, Boolean)

阻止当前线程,直到当前 WaitHandle 接收信号,使用 32 位有符号整数指定时间间隔,并指定是否在等待之前退出同步域。

(继承自 WaitHandle)
WaitOne(Int32)

阻止当前线程,直到当前 WaitHandle 接收信号,使用 32 位有符号整数指定时间间隔(以毫秒为单位)。

(继承自 WaitHandle)
WaitOne(TimeSpan, Boolean)

阻止当前线程,直到当前实例收到信号,使用指定 TimeSpan 时间间隔并指定是否在等待之前退出同步域。

(继承自 WaitHandle)
WaitOne(TimeSpan)

阻止当前线程,直到当前实例收到信号,并使用 TimeSpan 指定时间间隔。

(继承自 WaitHandle)

显式接口实现

名称 说明
IDisposable.Dispose()

此 API 支持产品基础结构,不能在代码中直接使用。

释放该 WaitHandle命令使用的所有资源。

(继承自 WaitHandle)

扩展方法

名称 说明
GetAccessControl(Mutex)

返回指定 mutex的安全描述符。

GetSafeWaitHandle(WaitHandle)

获取本机操作系统等待句柄的安全句柄。

SetAccessControl(Mutex, MutexSecurity)

设置指定互斥体的安全描述符。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

设置本机操作系统等待句柄的安全句柄。

适用于

线程安全性

此类型是线程安全的。

另请参阅