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 物件來同步存取受保護的資源。 因為每個呼叫執行緒在取得 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()
    {
        // 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) 方法來取得 mutex。 如果逾時間隔經過,則方法會 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 是同步處理基本類型,只授與共用資源的獨佔存取權給一個執行緒。 如果執行緒取得 mutex,則第二個想要取得 mutex 的執行緒會暫停,直到第一個執行緒釋放 mutex 為止。

重要

此型別代表 IDisposable 介面。 當您完成使用型別時,您應該直接或間接處置它。 若要直接處置型別,請呼叫其 try/catch 區塊中的 Dispose 方法。 若要間接處置它,請使用語言建構函式,例如 using (在 C# 中) 或 Using (在 Visual Basic 中)。 如需詳細資訊,請參閱 IDisposable 介面文章中的<使用實作 IDisposable 的物件>一節。

您可以使用 WaitHandle.WaitOne 方法來要求 mutex 的擁有權。 呼叫執行緒會封鎖,直到發生下列其中一項:

  • Mutex 會發出訊號,指出它不是擁有的。 發生這種情況時, WaitOne 方法會傳 true 回 ,而呼叫執行緒會假設 mutex 的擁有權,並存取由 mutex 保護的資源。 當資源完成存取之後,執行緒必須呼叫 ReleaseMutex 方法來釋放 mutex 的擁有權。 範例一節中的第一個範例說明此模式。

  • 呼叫 WaitOne 具有 或 timeout 參數的方法 millisecondsTimeout 所指定的逾時間隔已經過。 發生這種情況時, WaitOne 方法會傳 false 回 ,而呼叫執行緒不會進一步嘗試取得 mutex 的擁有權。 在此情況下,您應該建構程式碼,讓對受 mutex 保護的資源存取被拒絕給呼叫執行緒。 因為執行緒從未取得 mutex 的擁有權,所以它不得呼叫 ReleaseMutex 方法。 範例一節中的第二個範例說明此模式。

類別 Mutex 會強制執行執行緒識別,因此 Mutex 只能由取得它的執行緒釋放。 相反地,類別 Semaphore 不會強制執行執行緒識別。 Mutex 也可以跨應用程式域界限傳遞。

擁有 mutex 的執行緒可以在重複呼叫 WaitOne 中要求相同的 Mutex,而不會封鎖其執行。 不過,執行緒必須呼叫 ReleaseMutex 方法的相同次數,才能釋放 mutex 的擁有權。

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

如果執行緒在擁有 Mutex 時終止,則會放棄 mutex。 Mutex 的狀態會設定為已發出訊號,而下一個等候的執行緒會取得擁有權。 從 .NET Framework 2.0 版開始, AbandonedMutexException 會在下一個執行緒中擲回 ,以取得放棄的 mutex。 在 2.0 版.NET Framework之前,不會擲回例外狀況。

警告

放棄的 Mutex 通常表示程式碼中發生嚴重錯誤。 當執行緒在未釋放 Mutex 的情況下結束時,受 mutex 保護的資料結構可能不是一致的狀態。 要求 Mutex 擁有權的下一個執行緒可以處理此例外狀況,如果可以驗證資料結構的完整性,請繼續進行。

如果是全系統 Mutex,遭到放棄的 Mutex 可能表示應用程式已意外終止 (例如,透過使用「Windows 工作管理員」)。

Mutex 是兩種類型:未命名的本機 Mutex 和具名系統 Mutex。 本機 Mutex只存在於您的處理序內。 它可供進程中具有代表 mutex 之 物件的參考 Mutex 的任何執行緒使用。 每個未命名的物件都代表個別的 Mutex 本機 Mutex。

具名系統 Mutex 可在整個作業系統中看見,而且可用來同步處理進程的活動。 您可以使用接受名稱的建構函式,建立 Mutex 代表具名系統 Mutex 的物件。 您可以同時建立作業系統物件,也可以在建立 Mutex 物件之前存在。 您可以建立多個 Mutex 物件來代表同一個具名系統 Mutex,而且可以使用 OpenExisting 方法來開啟現有的具名系統 Mutex。

注意

在執行終端機服務的伺服器上,具名系統 Mutex 可以有兩個層級的可見度。 如果名稱開頭為 「Global \ 」,則 mutex 會顯示在所有終端機伺服器會話中。 如果名稱開頭為 「Local \ 」,則 mutex 只會顯示在建立它的終端機伺服器會話中。 在此情況下,具有相同名稱的個別 Mutex 可以存在於伺服器上的其他終端機伺服器會話中。 如果您在建立具名 Mutex 時未指定前置詞,則會採用前置詞 「Local \ 」。 在終端機伺服器會話中,兩個名稱只與其前置詞不同的 Mutex 是個別的 mutex,而且兩者都對終端機伺服器會話中的所有進程都可見。 也就是說,前置詞名稱 「Global \ 」 和 「Local \ 」 會描述相對於終端機伺服器會話的 Mutex 名稱範圍,而不是相對於進程。

反斜線 (\) 是 Mutex 名稱的保留字元。 請勿在 Mutex 名稱中使用反斜線 (\),除非在終端機伺服器工作階段中使用 Mutex 的注意事項中有指定。 否則,可能會擲回 DirectoryNotFoundException,即使是 Mutex 的名稱代表現有的檔案。

建構函式

Mutex()

使用預設屬性,初始化 Mutex 類別的新執行個體。

Mutex(Boolean)

使用布林值 (Boolean),初始化 Mutex 類別的新執行個體,指出呼叫執行緒是否應該具有 Mutex 的初始擁有權。

Mutex(Boolean, String)

使用布林值,初始化 Mutex 類別的新執行個體,指出呼叫執行緒是否應該具有 Mutex 的初始擁有權,並擁有為 Mutex 名稱的字串。

Mutex(Boolean, String, Boolean)

使用表示呼叫執行緒是否應該具有 Mutex 的初始擁有權的布林值、代表 Mutex 名稱的字串,以及當方法傳回時表示是否將 Mutex 的初始擁有權授與呼叫執行緒的布林值,初始化 Mutex 類別的新執行個體。

Mutex(Boolean, String, Boolean, MutexSecurity)

使用表示呼叫執行緒是否應該具有 Mutex 的初始擁有權的布林值、代表 Mutex 名稱的字串、當這個方法傳回時表示是否將 Mutex 的初始擁有權授與呼叫執行緒的布林值,以及要套用至具名 Mutex 的存取控制安全性,初始化 Mutex 類別的新執行個體。

欄位

WaitTimeout

表示 WaitAny(WaitHandle[], Int32, Boolean) 作業在發出任何等候控制代碼信號之前便已逾時。 這個欄位為常數。

(繼承來源 WaitHandle)

屬性

Handle
已過時。
已過時。

取得或設定原生 (Native) 的作業系統控制代碼。

(繼承來源 WaitHandle)
SafeWaitHandle

取得或設定原生 (Native) 的作業系統控制代碼。

(繼承來源 WaitHandle)

方法

Close()

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

(繼承來源 WaitHandle)
CreateObjRef(Type)

建立包含所有相關資訊的物件,這些資訊是產生用來與遠端物件通訊的所需 Proxy。

(繼承來源 MarshalByRefObject)
Dispose()

釋放 WaitHandle 類別目前的執行個體所使用的全部資源。

(繼承來源 WaitHandle)
Dispose(Boolean)

當在衍生類別中覆寫時,釋放 WaitHandle 所使用的 Unmanaged 資源,並選擇性釋放 Managed 資源。

(繼承來源 WaitHandle)
Equals(Object)

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

(繼承來源 Object)
GetAccessControl()

取得 MutexSecurity 物件,表示具名 Mutex 的存取控制安全性。

GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetLifetimeService()
已過時。

擷取控制這個執行個體存留期 (Lifetime) 原則的目前存留期服務物件。

(繼承來源 MarshalByRefObject)
GetType()

取得目前執行個體的 Type

(繼承來源 Object)
InitializeLifetimeService()
已過時。

取得存留期服務物件,以控制這個執行個體的存留期原則。

(繼承來源 MarshalByRefObject)
MemberwiseClone()

建立目前 Object 的淺層複製。

(繼承來源 Object)
MemberwiseClone(Boolean)

建立目前 MarshalByRefObject 物件的淺層複本。

(繼承來源 MarshalByRefObject)
OpenExisting(String)

開啟指定的具名 mutex (如果已經存在)。

OpenExisting(String, MutexRights)

使用所需的安全性存取權,開啟指定的具名 mutex (如果已經存在)。

ReleaseMutex()

釋出 Mutex 一次。

SetAccessControl(MutexSecurity)

為具名系統 Mutex 設定存取控制安全性。

ToString()

傳回代表目前物件的字串。

(繼承來源 Object)
TryOpenExisting(String, Mutex)

開啟指定的具名 mutex (如果已經存在),並傳回值,指出作業是否成功。

TryOpenExisting(String, MutexRights, Mutex)

使用所需的安全性存取權,開啟指定的具名 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)

傳回所指定 mutex 的安全性描述元。

SetAccessControl(Mutex, MutexSecurity)

設定所指定 mutex 的安全性描述元。

GetSafeWaitHandle(WaitHandle)

取得原生作業系統等候控制代碼的安全控制代碼。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

設定原生作業系統等候控制代碼的安全控制代碼。

適用於

執行緒安全性

此型別具備執行緒安全。

另請參閱