Mutex Třída
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Primitiva synchronizace, kterou lze použít také pro synchronizaci meziprocesů.
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í mutex, musí volat metodu ReleaseMutex uvolnění vlastnictví 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
V následujícím příkladu každé vlákno volá metodu WaitOne(Int32) získání mutex. Pokud časový limit uplynul, metoda vrátí falsea vlákno nezíská mutex ani získá 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řebuje současně přístup ke sdílenému prostředku, systém potřebuje synchronizační mechanismus, který zajistí, aby prostředek používal pouze jedno vlákno najednou. Mutex je primitivní 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, se pozastaví, dokud první vlákno nepustí mutex.
Důležité
Tento typ implementuje rozhraní IDisposable. Jakmile skončíte s používáním typu, měli byste ho odstranit buď přímo, nebo nepřímo. Chcete-li typ odstranit přímo, zavolejte jeho Dispose metodu v bloku try/catch. Pokud ho chcete zlikvidovat nepřímo, použijte konstruktor jazyka, jako je using (v jazyce C#) nebo Using (v jazyce Visual Basic). Další informace naleznete v části Použití objektu, který implementuje IDisposable v IDisposable tématu rozhraní.
Tuto metodu WaitHandle.WaitOne můžete použít k vyžádání vlastnictví mutexu. Volající vlákno blokuje, dokud nedojde k některé z následujících situací:
Mutex je signalizovat, že není vlastněný. V takovém případě WaitOne metoda vrátí
truea volající vlákno předpokládá vlastnictví mutex a přistupuje k prostředku chráněnému mutex. Po dokončení přístupu k prostředku musí vlákno volat metodu ReleaseMutex uvolnění vlastnictví mutex. Tento vzor znázorňuje první příklad v části Příklady.Časový limit zadaný v volání WaitOne metody, která má
millisecondsTimeoutnebotimeoutparametr uplynul. Pokud k tomu dojde, WaitOne metoda vrátífalsea volající vlákno se nebude dále pokoušet o získání vlastnictví mutex. V tomto případě byste měli strukturovat kód tak, aby přístup k prostředku chráněnému mutex byl odepřen volajícímu vláknu. Protože vlákno nikdy nezískala vlastnictví mutex, 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. Je také možné předat mutex přes hranice domény aplikace.
Vlákno, které vlastní mutex, může požádat o stejný mutex při opakovaných voláních WaitOne bez blokování jeho spuštění. Vlákno však musí volat metodu ReleaseMutex stejného počtu, aby se uvolnilo vlastnictví mutexu.
Vzhledem k tomu, že Mutex třída dědí z WaitHandle, můžete také volat statické WaitHandle.WaitAll a WaitHandle.WaitAny metody pro synchronizaci přístupu k chráněnému prostředku.
Pokud vlákno ukončí při vlastnictví mutexu, je mutex o tom, že je opuštěný. Stav mutexu je nastavený na signál a další čekající vlákno získá vlastnictví. Počínaje verzí 2.0 architektury .NET se v dalším vlákně vyvolá AbandonedMutexException, které získá opuštěný mutex. Před verzí 2.0 rozhraní .NET Framework nebyla vyvolán žádná výjimka.
Caution
Opuštěný mutex často značí závažnou chybu v kódu. Když vlákno opustí bez uvolnění mutexu, datové struktury chráněné mutex nemusí být v konzistentním stavu. Další vlákno, které požádá o vlastnictví mutex, může tuto výjimku zpracovat a pokračovat, pokud je možné ověřit integritu datových struktur.
V případě mutexu celého 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 mají dva typy: 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žívána libovolným vláknem ve vašem 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 lze je použít k synchronizaci aktivit procesů. Objekt, který představuje pojmenovaný systémový mutex, můžete vytvořit Mutex pomocí konstruktoru, který přijímá název. Objekt operačního systému lze vytvořit současně nebo může existovat před vytvořením objektu Mutex . Můžete vytvořit více objektů Mutex, které představují stejný pojmenovaný systémový mutex, a pomocí metody OpenExisting můžete otevřít existující pojmenovaný systémový mutex.
Note
Na serveru se spuštěnou terminálovou službou může pojmenovaný systémový mutex mít dvě úrovně viditelnosti. Pokud 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 byla vytvořena. V takovém případě může existovat samostatný mutex se stejným názvem v každé druhé relaci terminálového serveru na serveru. Pokud při vytváření pojmenovaného mutex nezadáte předponu, převezme předponu Local\. V rámci relace terminálového serveru jsou dva mutexy, jejichž názvy se liší pouze podle jejich předpon, 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í rozsah názvu mutex vzhledem k relacím terminálového serveru, nikoli vzhledem k procesům.
Caution
Ve výchozím nastavení není pojmenovaný mutex omezen na uživatele, který ho vytvořil. Ostatní uživatelé mohou být schopni otevřít a používat mutex, včetně zasahování do mutexu zadáním mutexu a jeho ukončením. V operačníchsystémechch Windows Pokud chcete omezit přístup konkrétním uživatelům, můžete při vytváření pojmenovaného mutex použít přetížení konstruktoru nebo MutexAcl a předat MutexSecurity. V operačních systémech unixových systémů v současné době neexistuje způsob, jak omezit přístup k pojmenované mutex. 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 se spuštěným kódem.
Zpětné lomítko (\) je vyhrazený znak v názvu mutex. Nepoužívejte zpětné lomítko (\) v názvu mutex s výjimkou toho, jak je uvedeno v poznámce při použití mutexů v relacích terminálového serveru. DirectoryNotFoundException Jinak může dojít k vyvolání, i když název mutex představuje existující soubor.
Konstruktory
| Name | Description |
|---|---|
| Mutex() |
Inicializuje novou instanci Mutex třídy s výchozími vlastnostmi. |
| Mutex(Boolean, String, Boolean, MutexSecurity) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno by mělo 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í mutex a zabezpečení řízení přístupu, které se má použít na pojmenovaný mutex. |
| Mutex(Boolean, String, Boolean) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno by mělo 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, NamedWaitHandleOptions, Boolean) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno by mělo mít počáteční vlastnictví mutex, řetězec, který je název mutex, možnosti nastavit uživatelský obor a relace-obor přístupu, a logickou hodnotu, která, když metoda vrátí, označuje, zda volající vlákno bylo uděleno počáteční vlastnictví mutex. |
| Mutex(Boolean, String, NamedWaitHandleOptions) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která indikuje, zda volající vlákno má mít počáteční vlastnictví mutex, řetězec, který je název mutex a možnosti pro nastavení přístupu k oboru uživatele a relace. |
| Mutex(Boolean, String) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno by mělo mít počáteční vlastnictví mutex, a řetězec, který je názvem mutex. |
| Mutex(Boolean) |
Inicializuje novou instanci Mutex třídy s logickou hodnotou, která označuje, zda volající vlákno by mělo mít počáteční vlastnictví mutex. |
| Mutex(String, NamedWaitHandleOptions) |
Inicializuje novou instanci Mutex třídy s řetězcem, který je názvem mutex a možnostmi pro nastavení uživatelského oboru a přístupu k oboru relace. Volající vlákno nevyžaduje počáteční vlastnictví mutexu. |
Pole
| Name | Description |
|---|---|
| WaitTimeout |
Označuje, že WaitAny(WaitHandle[], Int32, Boolean) operace vypršela před signálem jakéhokoli z popisovačů čekání. Toto pole je konstantní. (Zděděno od WaitHandle) |
Vlastnosti
| Name | Description |
|---|---|
| Handle |
Zastaralé.
Zastaralé.
Získá nebo nastaví nativní popisovač operačního systému. (Zděděno od WaitHandle) |
| SafeWaitHandle |
Získá nebo nastaví nativní popisovač operačního systému. (Zděděno od WaitHandle) |
Metody
| Name | Description |
|---|---|
| Close() |
Uvolní všechny prostředky uchovávané aktuálním WaitHandle. (Zděděno od WaitHandle) |
| CreateObjRef(Type) |
Vytvoří objekt, který obsahuje všechny relevantní informace potřebné k vygenerování proxy serveru sloužící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é nástrojem WaitHandlea volitelně uvolní spravované prostředky. (Zděděno od WaitHandle) |
| Equals(Object) |
Určuje, zda je zadaný objekt roven 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í funkce hash. (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á Type aktuální instance. (Zděděno od Object) |
| InitializeLifetimeService() |
Zastaralé.
Získá objekt služby životnosti pro řízení zásad životnosti pro tuto instanci. (Zděděno od MarshalByRefObject) |
| MemberwiseClone() |
Vytvoří mělkou kopii aktuálního Object. (Zděděno od Object) |
| MemberwiseClone(Boolean) |
Vytvoří mělkou kopii aktuálního MarshalByRefObject objektu. (Zděděno od MarshalByRefObject) |
| OpenExisting(String, MutexRights) |
Otevře zadaný pojmenovaný mutex, pokud již existuje, s požadovaným přístupem zabezpečení. |
| OpenExisting(String, NamedWaitHandleOptions) |
Otevře zadaný pojmenovaný mutex, pokud již existuje. Pokud jsou možnosti nastaveny pouze na aktuálního uživatele, ověří se u volajícího uživatele řízení přístupu objektu. |
| OpenExisting(String) |
Otevře zadaný pojmenovaný mutex, pokud již existuje. |
| 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, jestli operace proběhla úspěšně. |
| TryOpenExisting(String, NamedWaitHandleOptions, Mutex) |
Otevře zadaný pojmenovaný mutex, pokud již existuje, a vrátí hodnotu, která označuje, zda operace proběhla úspěšně. Pokud jsou možnosti nastaveny pouze na aktuálního uživatele, ověří se u volajícího uživatele řízení přístupu objektu. |
| WaitOne() |
Blokuje aktuální vlákno, dokud proud WaitHandle neobdrží signál. (Zděděno od WaitHandle) |
| WaitOne(Int32, Boolean) |
Zablokuje aktuální vlákno, dokud aktuální WaitHandle neobdrží signál, pomocí 32bitového znaménka integer určí časový interval a určí, jestli se má před čekáním ukončit synchronizační doména. (Zděděno od WaitHandle) |
| WaitOne(Int32) |
Blokuje aktuální vlákno, dokud aktuální WaitHandle neobdrží signál, pomocí 32bitového znaménka integer určuje časový interval v milisekundách. (Zděděno od WaitHandle) |
| WaitOne(TimeSpan, Boolean) |
Zablokuje aktuální vlákno, dokud aktuální instance neobdrží signál, pomocí parametru TimeSpan a určí, zda 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í TimeSpan k určení časového intervalu. (Zděděno od WaitHandle) |
Explicitní implementace rozhraní
| Name | Description |
|---|---|
| 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í
| Name | Description |
|---|---|
| GetAccessControl(Mutex) |
Vrátí popisovače zabezpečení pro zadanou |
| GetSafeWaitHandle(WaitHandle) |
Získá bezpečný popisovač pro nativní obslužný rutina čekání operačního systému. |
| SetAccessControl(Mutex, MutexSecurity) |
Nastaví popisovače zabezpečení pro zadaný mutex. |
| SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Nastaví bezpečný popisovač pro nativní obslužný rutinu čekání 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.