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 會發出訊號,指出它不是擁有的。 發生這種情況時,方法會 WaitOnetrue 回 ,而呼叫執行緒會假設 Mutex 的擁有權,並存取受 mutex 保護的資源。 當資源完成存取時,執行緒必須呼叫 ReleaseMutex 方法來釋放 Mutex 的擁有權。 一節中的第一個範例說明此模式。

  • 呼叫 WaitOne 具有 millisecondsTimeouttimeout 參數的方法所指定的逾時間隔已過。 發生這種情況時,方法會 WaitOnefalse 回 ,而呼叫執行緒不會進一步嘗試取得 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 而不要結束 Mutex 來干擾 mutex。 在類似 Unix 的作業系統上,檔案系統會用於具名 Mutex 的實作,而其他使用者可能會以更顯著的方式干擾具名 Mutex。 在 Windows 上,若要限制特定使用者的存取權,您可以使用建構函式多載,或在 MutexAcl 建立具名 Mutex 時傳入 MutexSecurity 。 在類似 Unix 的作業系統上,目前沒有任何方法可以限制對具名 Mutex 的存取。 避免在沒有存取限制的情況下使用具名 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)

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

適用於

執行緒安全性

此型別具備執行緒安全。

另請參閱