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,執行緒既未取得 mutex 也無法存取該 mutex 所保護的資源。 ReleaseMutex此方法僅由取得 mutex 的執行緒呼叫。

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 是一種同步原語,僅允許一個執行緒獨佔存取共享資源。 若執行緒取得互斥體,第二個想要取得該互斥體的執行緒會被暫停,直到第一個執行緒釋放該互斥體。

Important

此類型會實作 IDisposable 介面。 當您完成使用這個物品後,應直接或間接地處理它。 若要直接處置類型,請在 Disposetry/ 區塊中呼叫其 catch 方法。 若要間接處置它,請使用語言建構,例如 using (C#) 或 Using (在 Visual Basic 中)。 如需詳細資訊,請參閱介面主題中的 <使用實作 IDisposable 的物件>一節。

你可以用這個 WaitHandle.WaitOne 方法申請 mutex 的所有權。 呼叫執行緒會阻塞,直到以下其中一項發生:

  • 互斥線會被訊號表示該裝置未被擁有。 當此情況發生時, WaitOne 方法會回傳 true,呼叫執行緒會取得該互斥節的所有權,並存取由該互斥節保護的資源。 當執行緒完成存取資源後,必須呼叫該 ReleaseMutex 方法來解除對互斥組織的所有權。 範例部分的第一個例子說明了這種模式。

  • 呼叫包含 WaitOne or millisecondsTimeout 參數的方法時指定的逾時間隔timeout已過。 當此情況發生時, WaitOne 方法會回傳 false,呼叫執行緒不再嘗試取得該互斥組的所有權。 在這種情況下,你應該結構化程式碼,讓呼叫執行緒無法存取由 mutex 保護的資源。 由於執行緒從未取得 mutex 的所有權,因此它不能呼叫該 ReleaseMutex 方法。 範例部分的第二個例子說明了這種模式。

Mutex 類別強制執行緒身份,因此只有取得該執行緒的執行緒才能釋放互斥。 相較之下,該 Semaphore 類別不會強制執行緒身份。 互斥也可以跨越應用域邊界傳遞。

擁有 mutex 的執行緒可以在重複呼叫 中 WaitOne 請求相同的 mutex,而不會阻擋其執行。 然而,執行緒必須 ReleaseMutex 呼叫該方法的次數相同,才能解除對互斥單元的所有權。

由於該 Mutex 類別繼承自 WaitHandle,你也可以呼叫靜態 WaitHandle.WaitAllWaitHandle.WaitAny 方法來同步存取受保護資源。

若執行緒在擁有 mutex 時終止,則該 mutex 稱為放棄。 mutex 的狀態被設定為 signaled,下一個等待執行緒取得所有權。 從 .NET Framework 2.0 版本開始,下一個執行緒會丟棄 AbandonedMutexException。 在 .NET Framework 2.0 版本之前,沒有例外。

Caution

放棄的互斥體通常表示程式碼存在嚴重錯誤。 當執行緒退出時未釋放互斥體,受互斥體保護的資料結構可能不具一致性狀態。 下一個請求 mutex 擁有權的執行緒可以處理此例外並繼續進行,前提是資料結構的完整性能被驗證。

在全系統 Mutex 的情況下,已放棄的 Mutex 可能表示應用程式已突然終止(例如,使用 Windows 任務管理器)。

變異體分為兩種:局部互斥體,即無名的,以及命名系統互斥體。 本地互斥鎖只存在於您的程序內。 它可以被程序中任何有代表 Mutex mutex 物件參考的執行緒使用。 每個未命名 Mutex 的物件代表一個獨立的局部互斥體。

命名系統互斥位在整個作業系統中可見,並可用來同步程序的活動。 你可以透過使用接受名稱的建構子來建立 Mutex 一個代表命名系統互斥體的物件。 作業系統物件可以同時建立,也可以在物件建立 Mutex 前就已存在。 您可以建立多個 Mutex 代表相同具名系統 Mutex 的物件,而且您可以使用 OpenExisting 方法來開啟現有的具名系統 Mutex。

備註

在執行終端服務的伺服器上,命名的系統mutex可以有兩層可視性。 若其名稱以前綴 Global\開頭,該互斥在所有終端伺服器會話中可見。 若其名稱以前綴 Local\開頭,該互斥僅在建立該終端伺服器會話中可見。 在這種情況下,伺服器上其他終端伺服器會話中可以存在一個同名的獨立互斥機構。 如果你在建立命名的互斥組織時未指定前綴,則會取用前綴 Local\。 在終端伺服器會話中,兩個僅以前綴名稱不同的互斥是獨立的互斥,且兩者皆對終端伺服器會話中的所有程序可見。 也就是說,前綴名稱 Global\Local\ 描述了 mutex 名稱相對於終端伺服器會話的範圍,而非相對於程序的範圍。

Caution

預設情況下,命名的互斥機構不會限制於建立它的使用者。 其他使用者可能能夠開啟並使用互斥體,包括透過進入互斥體而不退出來干擾該互斥體。 在類 Unix 作業系統中,檔案系統用於命名互斥的實作,其他使用者可能能以更重要的方式干涉命名互斥。 在Windows中,為了限制特定使用者的存取,你可以使用建構子過載(MutexAcl,並在建立命名的 mutex 時傳遞 MutexSecurity。 在類 Unix 作業系統中,目前無法限制對命名互斥的存取。 避免在可能有不受信任使用者執行程式碼的系統中使用無存取限制的命名互斥節。

反斜線(\)是變音子名稱中的保留字元。 除非在終端伺服器會話中使用互斥位的說明中另有說明,否則不要在互斥位名稱中使用反斜線(\)。 否則,即使 mutex 名稱代表已存在的檔案,也可能拋出 a DirectoryNotFoundException

建構函式

名稱 Description
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 的初始擁有權、一個為 mutex 名稱的字串,以及設定使用者範圍與 session-scope 存取的選項。

Mutex(Boolean, String)

初始化一個新的類別實例 Mutex ,並以布林值表示呼叫執行緒是否應擁有該互斥線的初始擁有權,並初始化一個為該互斥節名稱的字串。

Mutex(Boolean)

初始化一個新的類別實例 Mutex ,並設定一個布林值,指示呼叫執行緒是否應該擁有該互斥體的初始擁有權。

Mutex(String, NamedWaitHandleOptions)

初始化一個新的類別實例 Mutex ,並以一個串列為互斥體名稱,並設定使用者範圍與會話範圍存取權的選項。 呼叫執行緒不會要求擁有 mutex 的初始擁有權。

欄位

名稱 Description
WaitTimeout

表示操作 WaitAny(WaitHandle[], Int32, Boolean) 在任何等待句柄被通知前已逾時。 此欄位是常數。

(繼承來源 WaitHandle)

屬性

名稱 Description
Handle
已淘汰.
已淘汰.

取得或設定原生作業系統的 handle 。

(繼承來源 WaitHandle)
SafeWaitHandle

取得或設定原生作業系統的 handle 。

(繼承來源 WaitHandle)

方法

名稱 Description
Close()

釋放目前 WaitHandle所持有的所有資源。

(繼承來源 WaitHandle)
CreateObjRef(Type)

建立物件,其中包含產生用來與遠端物件通訊之 Proxy 所需的所有相關信息。

(繼承來源 MarshalByRefObject)
Dispose()

釋放目前類別實例 WaitHandle 所使用的所有資源。

(繼承來源 WaitHandle)
Dispose(Boolean)

當在衍生類別中被覆寫時,會釋放 所使用的 WaitHandle非管理資源,並可選擇性地釋放受管理資源。

(繼承來源 WaitHandle)
Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
GetAccessControl()

取得 MutexSecurity 一個代表命名 mutex 存取控制安全性的物件。

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)

阻塞目前執行緒直到目前實例收到訊號,並用 a TimeSpan 指定時間區間,並決定是否在等待前退出同步域。

(繼承來源 WaitHandle)
WaitOne(TimeSpan)

阻塞目前執行緒直到目前實例收到訊號,並使用 a TimeSpan 指定時間區間。

(繼承來源 WaitHandle)

明確介面實作

名稱 Description
IDisposable.Dispose()

此 API 支援此產品基礎結構,但無法直接用於程式碼之中。

釋放所有由 WaitHandle.

(繼承來源 WaitHandle)

擴充方法

名稱 Description
GetAccessControl(Mutex)

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

GetSafeWaitHandle(WaitHandle)

取得原生作業系統等待句柄的安全句柄。

SetAccessControl(Mutex, MutexSecurity)

設定指定互斥組的安全描述符。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

為作業系統的原生等待句柄設定安全句柄。

適用於

執行緒安全性

此類型是安全線程。

另請參閱