Sdílet prostřednictvím


Mutex Třída

Definice

Primitivy synchronizace, které lze použít také pro synchronizaci mezi procesy.

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
Dědičnost
Dědičnost
Atributy

Příklady

Tento příklad ukazuje, jak se místní Mutex objekt používá k synchronizaci přístupu k chráněnému prostředku. Vzhledem k tomu, že každé volající vlákno je blokováno, dokud nezíská vlastnictví mutexu, musí volat metodu ReleaseMutex pro uvolnění vlastnictví mutexu.

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

V následujícím příkladu každé vlákno volá metodu WaitOne(Int32) pro získání mutexu. Pokud interval časového limitu uplyne, vrátí falsemetoda hodnotu a vlákno nezíská ani přístup k prostředku, který mutex chrání. Metoda ReleaseMutex je volána pouze vláknem, které získá 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

Poznámky

Pokud dvě nebo více vláken potřebují přístup ke sdílenému prostředku najednou, systém potřebuje synchronizační mechanismus, který zajistí, že prostředek bude používat jenom jedno vlákno najednou. Mutex je primitiv synchronizace, který uděluje výhradní přístup ke sdílenému prostředku pouze jednomu vláknu. Pokud vlákno získá mutex, druhé vlákno, které chce tento mutex získat, je pozastaveno, dokud první vlákno mutex nesvolí.

Důležité

Tento typ implementuje IDisposable rozhraní. Po dokončení používání tohoto typu byste ho měli přímo nebo nepřímo odstranit. Pokud chcete odstranit typ přímo, zavolejte jeho Dispose metodu try/catch v bloku. Pokud ho chcete odstranit nepřímo, použijte konstruktor jazyka, například using (v jazyce C#) nebo Using (v jazyce Visual Basic). Další informace najdete v části "Použití objektu, který implementuje IDisposable" v IDisposable tématu rozhraní.

Pomocí metody můžete WaitHandle.WaitOne požádat o vlastnictví mutexu. Volající vlákno blokuje, dokud nedojde k jedné z následujících:

  • Mutex je signalizovat, že není vlastněný. Když k tomu dojde, WaitOne metoda vrátí truea volající vlákno převezme vlastnictví mutexu a přistupuje k prostředku chráněnému mutexem. Po dokončení přístupu k prostředku musí vlákno volat metodu ReleaseMutex pro uvolnění vlastnictví mutexu. První příklad v části Příklady znázorňuje tento vzor.

  • Časový limit zadaný ve volání WaitOne metody s parametrem millisecondsTimeout nebo timeout uplynul. Když k tomu dojde, WaitOne metoda vrátí falsea volající vlákno se již nepokusí získat vlastnictví mutexu. V takovém případě byste měli kód strukturovat tak, aby byl volajícímu vláknu odepřen přístup k prostředku chráněnému mutexem. Protože vlákno nikdy nezískala vlastnictví mutexu, nesmí volat metodu ReleaseMutex . Druhý příklad v části Příklady znázorňuje tento vzor.

Třída Mutex vynucuje identitu vlákna, takže mutex může být uvolněn pouze vláknem, které ho získalo. Naproti tomu Semaphore třída nevynucuje identitu vlákna. Mutex je také možné předat přes hranice domény aplikace.

Vlákno, které vlastní mutex, může požadovat stejný mutex v opakovaných voláních bez WaitOne blokování jeho spuštění. Vlákno však musí volat metodu ReleaseMutex stejný počet, aby se uvolnilo vlastnictví mutexu.

Vzhledem k tomu, že Mutex třída dědí z WaitHandle, můžete také volat statické WaitHandle.WaitAll metody a WaitHandle.WaitAny synchronizovat přístup k chráněnému prostředku.

Pokud se vlákno ukončí při vlastnictví mutexu, říká se, že je mutex opuštěný. Stav mutexu je nastavený na signaled a další čekající vlákno získá vlastnictví. Počínaje verzí 2.0 rozhraní .NET Framework AbandonedMutexException je vyvolána v dalším vlákně, které získá opuštěný mutex. Před verzí 2.0 rozhraní .NET Framework nebyla vyvolán žádná výjimka.

Upozornění

Opuštěný mutex často značí vážnou chybu v kódu. Když vlákno opustí, aniž by uvolnilo mutex, datové struktury chráněné mutexem nemusí být v konzistentním stavu. Další vlákno, které požaduje vlastnictví mutexu, může tuto výjimku zpracovat a pokračovat, pokud je možné ověřit integritu datových struktur.

V případě mutexu v celém systému může opuštěný mutex znamenat, že aplikace byla náhle ukončena (například pomocí Správce úloh systému Windows).

Mutexy jsou dvou typů: místní mutexy, které nejsou pojmenovány, a pojmenované systémové mutexy. Místní mutex existuje pouze v rámci vašeho procesu. Může být použit libovolným vláknem v procesu, které má odkaz na Mutex objekt, který představuje mutex. Každý nepojmenovaný Mutex objekt představuje samostatný místní mutex.

Pojmenované systémové mutexy jsou viditelné v celém operačním systému a dají se použít k synchronizaci aktivit procesů. Pomocí konstruktoru Mutex , který přijímá název, můžete vytvořit objekt, který představuje pojmenovaný systémový mutex. Objekt operačního systému může být vytvořen současně nebo může existovat před vytvořením objektu Mutex . Můžete vytvořit více Mutex objektů, které představují stejný pojmenovaný systémový mutex, a můžete použít metodu OpenExisting k otevření existující pojmenované systémové mutex.

Poznámka

Na serveru, na kterém běží Terminálová služba, může mít pojmenovaný systémový mutex dvě úrovně viditelnosti. Pokud jeho název začíná předponou Global\, je mutex viditelný ve všech relacích terminálového serveru. Pokud jeho název začíná předponou Local\, je mutex viditelný pouze v relaci terminálového serveru, kde byl vytvořen. V takovém případě může v každé další relaci terminálového serveru na serveru existovat samostatný mutex se stejným názvem. Pokud při vytváření pojmenovaného mutexu nezadáte předponu, převezme předponu Local\. V relaci terminálového serveru jsou dva mutexy, jejichž názvy se liší pouze svými předponami, samostatné mutexy a oba jsou viditelné pro všechny procesy v relaci terminálového serveru. To znamená, že názvy Global\ předpon a Local\ popisují obor názvu mutex vzhledem k relacím terminálového serveru, nikoli vzhledem k procesům.

Upozornění

Ve výchozím nastavení není pojmenovaný mutex omezen na uživatele, který ho vytvořil. Jiní uživatelé můžou mutex otevřít a používat, včetně narušení mutexu tím, že do mutexu vstoupí a neopouští ho. V unixových operačních systémech se systém souborů používá při implementaci pojmenovaných mutexů a jiní uživatelé mohou být schopni ovlivňovat pojmenované mutexy významnějšími způsoby. Pokud chcete ve Windows omezit přístup na konkrétní uživatele, můžete při vytváření pojmenovaného mutexu použít přetížení konstruktoru nebo MutexAcl předat MutexSecurity . V unixových operačních systémech v současné době neexistuje způsob, jak omezit přístup k pojmenovaným mutexům. Vyhněte se používání pojmenovaných mutexů bez omezení přístupu v systémech, které můžou mít nedůvěryhodné uživatele s kódem.

Zpětné lomítko (\) je vyhrazený znak v názvu mutex. Nepoužívejte zpětné lomítko (\) v názvu mutexu s výjimkou případů uvedených v poznámce o použití mutexů v relacích terminálového serveru. V opačném DirectoryNotFoundException případě může být vyvolán, i když název mutex představuje existující soubor.

Konstruktory

Mutex()

Inicializuje novou instanci třídy s výchozími Mutex vlastnostmi.

Mutex(Boolean)

Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda má volající vlákno mít počáteční vlastnictví mutex.

Mutex(Boolean, String)

Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda má volající vlákno mít počáteční vlastnictví mutex, a řetězec, který je názvem mutex.

Mutex(Boolean, String, Boolean)

Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno má mít počáteční vlastnictví mutex, řetězec, který je název mutex, a logická hodnota, která, když metoda vrátí, označuje, zda volající vlákno bylo uděleno počáteční vlastnictví mutex.

Mutex(Boolean, String, Boolean, MutexSecurity)

Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno má mít počáteční vlastnictví mutex, řetězec, který je název mutex, logická proměnná, která, když metoda vrátí, označuje, zda volající vlákno bylo uděleno počáteční vlastnictví mutexu, a zabezpečení řízení přístupu, které se má použít na pojmenovaný mutex.

Pole

WaitTimeout

Označuje, že WaitAny(WaitHandle[], Int32, Boolean) časový limit operace vypršel před signálem některého z popisovačů čekání. Toto pole je konstantní.

(Zděděno od WaitHandle)

Vlastnosti

Handle
Zastaralé.
Zastaralé.

Získá nebo nastaví popisovač nativního operačního systému.

(Zděděno od WaitHandle)
SafeWaitHandle

Získá nebo nastaví popisovač nativního operačního systému.

(Zděděno od WaitHandle)

Metody

Close()

Uvolní všechny prostředky, které má aktuální WaitHandle.

(Zděděno od WaitHandle)
CreateObjRef(Type)

Vytvoří objekt, který obsahuje všechny relevantní informace potřebné k vygenerování proxy používaného ke komunikaci se vzdáleným objektem.

(Zděděno od MarshalByRefObject)
Dispose()

Uvolní všechny prostředky používané aktuální instancí WaitHandle třídy.

(Zděděno od WaitHandle)
Dispose(Boolean)

Při přepsání v odvozené třídě uvolní nespravované prostředky používané WaitHandlenástrojem a volitelně uvolní spravované prostředky.

(Zděděno od WaitHandle)
Equals(Object)

Určí, zda se zadaný objekt rovná aktuálnímu objektu.

(Zděděno od Object)
GetAccessControl()

MutexSecurity Získá objekt, který představuje zabezpečení řízení přístupu pro pojmenované mutex.

GetHashCode()

Slouží jako výchozí hashovací funkce.

(Zděděno od Object)
GetLifetimeService()
Zastaralé.

Načte objekt služby aktuální životnosti, který řídí zásady životnosti pro tuto instanci.

(Zděděno od MarshalByRefObject)
GetType()

Získá aktuální Type instanci.

(Zděděno od Object)
InitializeLifetimeService()
Zastaralé.

Získá objekt služby životnosti, který řídí zásady životnosti pro tuto instanci.

(Zděděno od MarshalByRefObject)
MemberwiseClone()

Vytvoří mělkou kopii aktuálního Objectsouboru .

(Zděděno od Object)
MemberwiseClone(Boolean)

Vytvoří mělkou kopii aktuálního MarshalByRefObject objektu.

(Zděděno od MarshalByRefObject)
OpenExisting(String)

Otevře zadaný pojmenovaný mutex, pokud již existuje.

OpenExisting(String, MutexRights)

Otevře zadaný pojmenovaný mutex, pokud již existuje, s požadovaným přístupem zabezpečení.

ReleaseMutex()

Uvolní jednou Mutex .

SetAccessControl(MutexSecurity)

Nastaví zabezpečení řízení přístupu pro pojmenovaný systémový mutex.

ToString()

Vrátí řetězec, který představuje aktuální objekt.

(Zděděno od Object)
TryOpenExisting(String, Mutex)

Otevře zadaný pojmenovaný mutex, pokud již existuje, a vrátí hodnotu, která označuje, zda operace proběhla úspěšně.

TryOpenExisting(String, MutexRights, Mutex)

Otevře zadaný pojmenovaný mutex, pokud již existuje, s požadovaným přístupem zabezpečení a vrátí hodnotu, která označuje, zda operace byla úspěšná.

WaitOne()

Blokuje aktuální vlákno, dokud proud WaitHandle neobdrží signál.

(Zděděno od WaitHandle)
WaitOne(Int32)

Blokuje aktuální vlákno, dokud proud WaitHandle neobdrží signál, pomocí 32bitového celého čísla se znaménkem určuje časový interval v milisekundách.

(Zděděno od WaitHandle)
WaitOne(Int32, Boolean)

Blokuje aktuální vlákno, dokud proud WaitHandle neobdrží signál. Pomocí 32bitového celého čísla se znaménkem určuje časový interval a určuje, jestli se má před čekáním ukončit synchronizační doména.

(Zděděno od WaitHandle)
WaitOne(TimeSpan)

Blokuje aktuální vlákno, dokud aktuální instance neobdrží signál pomocí parametru TimeSpan pro určení časového intervalu.

(Zděděno od WaitHandle)
WaitOne(TimeSpan, Boolean)

Zablokuje aktuální vlákno, dokud aktuální instance neobdrží signál. Použije TimeSpan k určení časového intervalu a určí, jestli se má před čekáním ukončit synchronizační doména.

(Zděděno od WaitHandle)

Explicitní implementace rozhraní

IDisposable.Dispose()

Toto rozhraní API podporuje produktovou infrastrukturu a není určené k použití přímo z uživatelského kódu.

Uvolní všechny prostředky používané nástrojem WaitHandle.

(Zděděno od WaitHandle)

Metody rozšíření

GetAccessControl(Mutex)

Vrátí popisovače zabezpečení pro zadaný mutex.

SetAccessControl(Mutex, MutexSecurity)

Nastaví popisovače zabezpečení pro zadaný mutex.

GetSafeWaitHandle(WaitHandle)

Získá bezpečný popisovač pro nativní operační systém čekání popisovač.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Nastaví bezpečný popisovač pro čekací úchyt nativního operačního systému.

Platí pro

Bezpečný přístup z více vláken

Tento typ je bezpečný pro přístup z více vláken.

Viz také