Mutex Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Element pierwotny synchronizacji, który może być również używany do synchronizacji międzyprocesowej.
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
- Dziedziczenie
- Dziedziczenie
- Atrybuty
Przykłady
W tym przykładzie pokazano, jak obiekt lokalny Mutex jest używany do synchronizowania dostępu do chronionego zasobu. Ponieważ każdy wątek wywołujący jest blokowany, dopóki nie uzyska własności mutex, musi wywołać metodę ReleaseMutex w celu zwolnienia własności 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
W poniższym przykładzie każdy wątek wywołuje metodę WaitOne(Int32) w celu uzyskania mutexu. Jeśli interwał limitu czasu upłynął, metoda zwraca false
wartość , a wątek nie uzyskuje ani mutex, ani nie uzyskuje dostępu do zasobu chronionego przez mutex. Metoda ReleaseMutex jest wywoływana tylko przez wątek, który uzyskuje 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
Uwagi
Gdy co najmniej dwa wątki muszą jednocześnie uzyskać dostęp do zasobu udostępnionego, system potrzebuje mechanizmu synchronizacji, aby upewnić się, że tylko jeden wątek w danym momencie używa zasobu. Mutex jest elementem pierwotnym synchronizacji, który udziela wyłącznego dostępu do zasobu udostępnionego tylko do jednego wątku. Jeśli wątek uzyskuje mutex, drugi wątek, który chce uzyskać ten mutex jest zawieszony, dopóki pierwszy wątek nie zwolni mutex.
Ważne
Ten typ implementuje IDisposable interfejs. Po zakończeniu korzystania z typu należy go usunąć bezpośrednio lub pośrednio. Aby usunąć typ bezpośrednio, wywołaj metodę Disposetry
/catch
w bloku. Aby usunąć go pośrednio, użyj konstrukcji językowej, takiej jak using
(w języku C#) lub Using
(w Visual Basic). Aby uzyskać więcej informacji, zobacz sekcję "Using an Object that Implements IDisposable" (Używanie obiektu implementujące protokół IDisposable) w temacie interfejsu IDisposable .
Możesz użyć WaitHandle.WaitOne metody , aby zażądać własności mutex. Wątek wywołujący blokuje się do momentu wystąpienia jednego z następujących elementów:
Mutex jest sygnalizowany, aby wskazać, że nie jest własnością. W WaitOne takim przypadku metoda zwraca
true
metodę , a wątek wywołujący przyjmuje własność mutex i uzyskuje dostęp do zasobu chronionego przez mutex. Po zakończeniu uzyskiwania dostępu do zasobu wątek musi wywołać ReleaseMutex metodę, aby zwolnić własność mutexu. Pierwszy przykład w sekcji Przykłady ilustruje ten wzorzec.Interwał limitu czasu określony w wywołaniu WaitOne metody, która ma
millisecondsTimeout
parametr ortimeout
, upłynął. W takim przypadku WaitOne metoda zwracafalse
metodę , a wątek wywołujący nie podejmuje dalszych prób uzyskania własności mutexu. W takim przypadku należy sstrukturę kodu tak, aby dostęp do zasobu chronionego przez mutex został odrzucony do wywołującego wątku. Ponieważ wątek nigdy nie nabył własności mutex, nie może wywołać ReleaseMutex metody . Drugi przykład w sekcji Przykłady ilustruje ten wzorzec.
Klasa Mutex wymusza tożsamość wątku, więc mutex może zostać zwolniony tylko przez wątek, który go nabył. Natomiast Semaphore klasa nie wymusza tożsamości wątku. Mutex można również przekazać przez granice domeny aplikacji.
Wątek, który jest właścicielem mutex, może zażądać tego samego mutexu w powtarzających się wywołaniach bez WaitOne blokowania jego wykonywania. Jednak wątek musi wywołać ReleaseMutex tę samą liczbę razy, aby zwolnić własność mutexu.
Mutex Ponieważ klasa dziedziczy z WaitHandleklasy , można również wywołać metody statyczne WaitHandle.WaitAll i WaitHandle.WaitAny w celu zsynchronizowania dostępu do chronionego zasobu.
Jeśli wątek kończy się, będąc właścicielem mutex, mutex mówi się, że zostanie porzucony. Stan mutex jest ustawiony na sygnalizowany, a następny wątek oczekujących otrzymuje własność. Począwszy od wersji 2.0 .NET Framework, AbandonedMutexException jest zgłaszany w następnym wątku, który uzyskuje porzucony mutex. Przed wersją 2.0 .NET Framework nie zgłoszono wyjątku.
Przestroga
Porzucony mutex często wskazuje poważny błąd w kodzie. Gdy wątek kończy się bez zwalniania mutexu, struktury danych chronione przez mutex mogą nie być w stanie spójnym. Następny wątek żądania własności mutex może obsłużyć ten wyjątek i kontynuować, jeśli można zweryfikować integralność struktur danych.
W przypadku mutexu całego systemu porzucony mutex może wskazywać, że aplikacja została nagle zakończona (na przykład przy użyciu Menedżera zadań systemu Windows).
Mutexes to dwa typy: lokalne mutexy, które są nienazwane i nazwane mutexes systemu. Lokalny mutex istnieje tylko w ramach procesu. Może być używany przez dowolny wątek w procesie, który ma odwołanie do Mutex obiektu, który reprezentuje mutex. Każdy nienazwany Mutex obiekt reprezentuje oddzielny lokalny mutex.
Nazwane mutexy systemu są widoczne w całym systemie operacyjnym i mogą służyć do synchronizowania działań procesów. Obiekt reprezentujący nazwany mutex systemu można utworzyć Mutex przy użyciu konstruktora, który akceptuje nazwę. Obiekt systemu operacyjnego można utworzyć w tym samym czasie lub może istnieć przed utworzeniem Mutex obiektu. Można utworzyć wiele Mutex obiektów, które reprezentują te same nazwane mutex systemu, i można użyć OpenExisting metody , aby otworzyć istniejący nazwany mutex systemu.
Uwaga
Na serwerze z uruchomionymi usługami terminali nazwany mutex systemu może mieć dwa poziomy widoczności. Jeśli jego nazwa zaczyna się od prefiksu Global\
, mutex jest widoczny we wszystkich sesjach serwera terminali. Jeśli jego nazwa zaczyna się od prefiksu Local\
, mutex jest widoczny tylko w sesji serwera terminalu, w której został utworzony. W takim przypadku oddzielny mutex o tej samej nazwie może istnieć w każdej z pozostałych sesji serwera terminalu na serwerze. Jeśli nie określisz prefiksu podczas tworzenia nazwanego mutexu, przyjmuje prefiks Local\
. W sesji serwera terminalu dwa elementy mutex, których nazwy różnią się tylko ich prefiksami, są oddzielnymi mutexami, a oba są widoczne dla wszystkich procesów w sesji serwera terminalu. Oznacza to, że nazwy Global\
prefiksów i Local\
opisują zakres nazwy mutex względem sesji serwera terminali, a nie względem procesów.
Przestroga
Domyślnie nazwany mutex nie jest ograniczony do użytkownika, który go utworzył. Inni użytkownicy mogą być w stanie otworzyć i użyć mutex, w tym zakłócać działanie mutex, wprowadzając mutex i nie zamykając go. W systemach operacyjnych podobnych do unix system plików jest używany w implementacji nazwanych mutexes, a inni użytkownicy mogą zakłócać nazwane mutexes w bardziej znaczący sposób. W systemie Windows, aby ograniczyć dostęp do określonych użytkowników, można użyć przeciążenia konstruktora lub MutexAcl przekazać MutexSecurity element podczas tworzenia nazwanego mutexu. Obecnie w systemach operacyjnych podobnych do systemu Unix nie ma możliwości ograniczenia dostępu do nazwanego mutexu. Unikaj używania nazwanych mutexes bez ograniczeń dostępu w systemach, które mogą mieć niezaufanych użytkowników z uruchomionym kodem.
Ukośnik odwrotny (\) jest zastrzeżonym znakiem w nazwie mutex. Nie należy używać ukośnika odwrotnego (\) w nazwie mutex z wyjątkiem określonej w notatce dotyczącej używania mutexes w sesjach serwera terminali. DirectoryNotFoundException W przeciwnym razie może zostać zgłoszony błąd, mimo że nazwa mutex reprezentuje istniejący plik.
Konstruktory
Mutex() |
Inicjuje Mutex nowe wystąpienie klasy z domyślnymi właściwościami. |
Mutex(Boolean) |
Inicjuje nowe wystąpienie Mutex klasy z wartością logiczną wskazującą, czy wątek wywołujący powinien mieć początkową własność mutexu. |
Mutex(Boolean, String) |
Inicjuje nowe wystąpienie Mutex klasy z wartością logiczną wskazującą, czy wątek wywołujący powinien mieć początkową własność mutex, oraz ciąg, który jest nazwą mutexu. |
Mutex(Boolean, String, Boolean) |
Inicjuje nowe wystąpienie Mutex klasy z wartością logiczną wskazującą, czy wątek wywołujący powinien mieć własność początkową mutex, ciąg, który jest nazwą mutex, oraz wartość logiczną, która, gdy metoda zwraca, wskazuje, czy wątek wywołujący otrzymał wstępną własność mutexu. |
Mutex(Boolean, String, Boolean, MutexSecurity) |
Inicjuje nowe wystąpienie Mutex klasy z wartością logiczną wskazującą, czy wątek wywołujący powinien mieć początkową własność mutex, ciąg, który jest nazwą mutex, zmienną logiczną, która, gdy metoda zwraca, wskazuje, czy wątek wywołujący otrzymał wstępną własność mutex, oraz zabezpieczenia kontroli dostępu, które mają być stosowane do nazwanego mutexu. |
Pola
WaitTimeout |
Wskazuje, że WaitAny(WaitHandle[], Int32, Boolean) upłynął limit czasu operacji, zanim którykolwiek z uchwytów oczekiwania został zasygnalizowany. To pole jest stałe. (Odziedziczone po WaitHandle) |
Właściwości
Handle |
Przestarzałe.
Przestarzałe.
Pobiera lub ustawia natywny uchwyt systemu operacyjnego. (Odziedziczone po WaitHandle) |
SafeWaitHandle |
Pobiera lub ustawia natywny uchwyt systemu operacyjnego. (Odziedziczone po WaitHandle) |
Metody
Close() |
Zwalnia wszystkie zasoby przechowywane przez bieżący WaitHandleelement . (Odziedziczone po WaitHandle) |
CreateObjRef(Type) |
Tworzy obiekt zawierający wszystkie istotne informacje wymagane do wygenerowania serwera proxy używanego do komunikowania się z obiektem zdalnym. (Odziedziczone po MarshalByRefObject) |
Dispose() |
Zwalnia wszystkie zasoby używane przez bieżące wystąpienie klasy WaitHandle. (Odziedziczone po WaitHandle) |
Dispose(Boolean) |
Po zastąpieniu w klasie pochodnej zwalnia niezarządzane zasoby używane przez WaitHandleprogram i opcjonalnie zwalnia zarządzane zasoby. (Odziedziczone po WaitHandle) |
Equals(Object) |
Określa, czy dany obiekt jest taki sam, jak bieżący obiekt. (Odziedziczone po Object) |
GetAccessControl() |
MutexSecurity Pobiera obiekt reprezentujący zabezpieczenia kontroli dostępu dla nazwanego mutexu. |
GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
GetLifetimeService() |
Przestarzałe.
Pobiera bieżący obiekt usługi okresu istnienia, który kontroluje zasady okresu istnienia dla tego wystąpienia. (Odziedziczone po MarshalByRefObject) |
GetType() |
Type Pobiera bieżące wystąpienie. (Odziedziczone po Object) |
InitializeLifetimeService() |
Przestarzałe.
Uzyskuje obiekt usługi okresu istnienia, aby kontrolować zasady okresu istnienia dla tego wystąpienia. (Odziedziczone po MarshalByRefObject) |
MemberwiseClone() |
Tworzy płytkią kopię bieżącego Objectelementu . (Odziedziczone po Object) |
MemberwiseClone(Boolean) |
Tworzy płytkią kopię bieżącego MarshalByRefObject obiektu. (Odziedziczone po MarshalByRefObject) |
OpenExisting(String) |
Otwiera określony o nazwie mutex, jeśli już istnieje. |
OpenExisting(String, MutexRights) |
Otwiera określony nazwany mutex, jeśli już istnieje, z żądanym dostępem zabezpieczeń. |
ReleaseMutex() |
Zwalnia raz Mutex . |
SetAccessControl(MutexSecurity) |
Ustawia zabezpieczenia kontroli dostępu dla nazwanego mutexu systemowego. |
ToString() |
Zwraca ciąg reprezentujący bieżący obiekt. (Odziedziczone po Object) |
TryOpenExisting(String, Mutex) |
Otwiera określony nazwany mutex, jeśli już istnieje, i zwraca wartość wskazującą, czy operacja zakończyła się pomyślnie. |
TryOpenExisting(String, MutexRights, Mutex) |
Otwiera określony nazwany mutex, jeśli już istnieje, z żądanym dostępem zabezpieczeń i zwraca wartość wskazującą, czy operacja zakończyła się pomyślnie. |
WaitOne() |
Blokuje bieżący wątek, dopóki bieżący WaitHandle nie otrzyma sygnału. (Odziedziczone po WaitHandle) |
WaitOne(Int32) |
Blokuje bieżący wątek do WaitHandle momentu odebrania sygnału przy użyciu 32-bitowej liczby całkowitej podpisanej w celu określenia interwału czasu w milisekundach. (Odziedziczone po WaitHandle) |
WaitOne(Int32, Boolean) |
Blokuje bieżący wątek do WaitHandle momentu odebrania sygnału przy użyciu 32-bitowej liczby całkowitej podpisanej w celu określenia interwału czasu i określenia, czy należy zamknąć domenę synchronizacji przed oczekiwaniem. (Odziedziczone po WaitHandle) |
WaitOne(TimeSpan) |
Blokuje bieżący wątek, dopóki bieżące wystąpienie nie otrzyma sygnału przy użyciu elementu , TimeSpan aby określić interwał czasu. (Odziedziczone po WaitHandle) |
WaitOne(TimeSpan, Boolean) |
Blokuje bieżący wątek, dopóki bieżące wystąpienie nie otrzyma sygnału, przy użyciu elementu , TimeSpan aby określić interwał czasu i określić, czy należy zamknąć domenę synchronizacji przed oczekiwaniem. (Odziedziczone po WaitHandle) |
Jawne implementacje interfejsu
IDisposable.Dispose() |
Ten interfejs API obsługuje infrastrukturę produktu i nie jest przeznaczony do użycia bezpośrednio z poziomu kodu. Zwalnia wszelkie zasoby używane przez element WaitHandle. (Odziedziczone po WaitHandle) |
Metody rozszerzania
GetAccessControl(Mutex) |
Zwraca deskryptory zabezpieczeń dla określonego |
SetAccessControl(Mutex, MutexSecurity) |
Ustawia deskryptory zabezpieczeń dla określonego mutexu. |
GetSafeWaitHandle(WaitHandle) |
Pobiera bezpieczny uchwyt dla natywnego uchwytu oczekiwania systemu operacyjnego. |
SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Ustawia bezpieczny uchwyt dla natywnego uchwytu oczekiwania systemu operacyjnego. |
Dotyczy
Bezpieczeństwo wątkowe
Ten typ jest bezpieczny wątkowo.