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 объект используется для синхронизации доступа к защищенному ресурсу. Так как каждый вызывающий поток блокируется, пока он не получит владение мьютексом, он должен вызвать ReleaseMutex метод для освобождения владения мьютексом.
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) метод для получения мьютекса. Если интервал ожидания истекает, метод возвращается false, а поток не получает мьютекс и не получает доступ к ресурсу, который защищает мьютекс. Метод ReleaseMutex вызывается только потоком, который получает мьютекс.
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 — это примитив синхронизации, предоставляющий монопольный доступ к общему ресурсу только одному потоку. Если поток получает мьютекс, второй поток, который хочет получить этот мьютекс, приостанавливается до тех пор, пока первый поток не освобождает мьютекс.
Это важно
Этот тип реализует IDisposable интерфейс. Завершив использование типа, следует избавиться от него напрямую или косвенно. Чтобы удалить тип напрямую, вызовите его Dispose метод в блоке try/catch . Чтобы удалить его косвенно, используйте конструкцию языка, например using (в C#) или Using (в Visual Basic). Дополнительные сведения см. в разделе "Использование объекта, реализующего IDisposable" в IDisposable разделе интерфейса.
Метод можно использовать WaitHandle.WaitOne для запроса владения мьютексом. Вызывающий поток блокируется до тех пор, пока не произойдет одно из следующих действий:
Мьютекс сигнализирует о том, что он не принадлежит. В этом случае WaitOne метод возвращается
true, и вызывающий поток принимает владение мьютексом и обращается к ресурсу, защищенному мьютексом. После завершения доступа к ресурсу поток должен вызвать ReleaseMutex метод, чтобы освободить владение мьютексом. Первый пример в разделе "Примеры" иллюстрирует этот шаблон.Интервал времени ожидания, указанный в вызове WaitOne метода, который имеет
millisecondsTimeoutилиtimeoutпараметр истек. В этом случае WaitOne метод возвращаетсяfalse, и вызывающий поток не пытается получить владение мьютексом. В этом случае необходимо структурировать код таким образом, чтобы доступ к ресурсу, защищенному мьютексом, запрещен в вызывающий поток. Так как поток никогда не приобрел владение мьютексом, он не должен вызывать ReleaseMutex метод. Второй пример в разделе "Примеры" иллюстрирует этот шаблон.
Класс Mutex применяет удостоверение потока, поэтому мьютекс может быть выпущен только потоком, который приобрел его. Напротив, Semaphore класс не применяет удостоверение потока. Мьютекс также можно передавать через границы домена приложения.
Поток, принадлежащий мьютексу, может запрашивать тот же мьютекс в повторяющихся WaitOne вызовах без блокировки его выполнения. Однако поток должен вызывать ReleaseMutex метод одинаковое количество раз, чтобы освободить владение мьютексом.
Mutex Так как класс наследует отWaitHandle, можно также вызвать статические WaitHandle.WaitAll и WaitHandle.WaitAny методы для синхронизации доступа к защищенному ресурсу.
Если поток завершается при владении мьютексом, мьютекс, как говорят, будет оставлен. Состояние мьютекса сигнализируется, а следующий поток ожидания получает владение. Начиная с версии 2.0 платформы .NET Framework, в следующем потоке создается AbandonedMutexException, который получает заброшенный мьютекс. До версии 2.0 платформы .NET Framework исключение не было создано.
Предостережение
Заброшенный мьютекс часто указывает на серьезную ошибку в коде. Когда поток завершает работу без освобождения мьютекса, структуры данных, защищенные мьютексом, могут не находиться в согласованном состоянии. Следующий поток для запроса владения мьютексом может обработать это исключение и продолжить, если можно проверить целостность структур данных.
В случае системного мьютекса заброшенный мьютекс может указать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows).
Мьютексы имеют два типа: локальные мьютексы, которые не именуются и именованные системные мьютексы. Локальный мьютекс существует только в вашем процессе. Его можно использовать любым потоком в процессе, который имеет ссылку на Mutex объект, представляющий мьютекс. Каждый неименованный Mutex объект представляет отдельный локальный мьютекс.
Именованные системные мьютексы отображаются во всей операционной системе и могут использоваться для синхронизации действий процессов. Объект, представляющий именованный Mutex системный мьютекс, можно создать с помощью конструктора, который принимает имя. Объект операционной системы можно создать одновременно или он может существовать перед созданием Mutex объекта. Можно создать несколько объектов Mutex, которые представляют один и тот же именованный системный мьютекс, и использовать метод OpenExisting для открытия существующего именованного системного мьютекса.
Note
На сервере, на котором выполняются службы терминалов, именованный системный мьютекс может иметь два уровня видимости. Если его имя начинается с префикса Global\, мьютекс отображается во всех сеансах сервера терминала. Если его имя начинается с префикса Local\, мьютекс отображается только в сеансе сервера терминала, где он был создан. В этом случае отдельный мьютекс с тем же именем может существовать в каждом из других сеансов сервера терминала на сервере. Если при создании именованного мьютекса не указан префикс, он принимает префикс Local\. В сеансе сервера терминала два мьютекса, имена которых отличаются только по их префиксам, являются отдельными мьютексами, и оба являются видимыми для всех процессов в сеансе сервера терминала. То есть имена Global\ префиксов и Local\ описание области имени мьютекса относительно сеансов сервера терминала, а не относительно процессов.
Предостережение
По умолчанию именованный мьютекс не ограничивается пользователем, создающим его. Другие пользователи могут открывать и использовать мьютекс, включая вмешательство в мьютекс, вводя мьютекс и не выходя из него. В операционных системах, таких как Unix, файловая система используется в реализации именованных мьютексов, а другие пользователи могут вмешиваться в именованные мьютексы более значительными способами. Windows Для ограничения доступа к определенным пользователям можно использовать перегрузку конструктора или MutexAcl и передать MutexSecurity при создании именованного мьютекса. В операционных системах, таких как Unix, в настоящее время нет способа ограничить доступ к именованному мьютексу. Избегайте использования именованных мьютексов без ограничений доступа в системах, которые могут иметь ненадежных пользователей, выполняющих код.
Обратная косая черта (\) — это зарезервированный символ в имени мьютекса. Не используйте обратную косую черту (\) в имени мьютекса, за исключением указанного в заметке об использовании мьютексов в сеансах сервера терминалов. В противном случае может возникать исключение, DirectoryNotFoundException даже если имя мьютекса представляет существующий файл.
Конструкторы
| Имя | Описание |
|---|---|
| Mutex() |
Инициализирует новый экземпляр Mutex класса со свойствами по умолчанию. |
| Mutex(Boolean, String, Boolean, MutexSecurity) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом, строка, представляющая имя мьютекса, логическая переменная, которая, когда метод возвращает, указывает, был ли вызывающий поток предоставлен начальное владение мьютексом, а также безопасность управления доступом, применяемая к именованной мьютексе. |
| Mutex(Boolean, String, Boolean) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом, строку, которая является именем мьютекса, и логическое значение, которое, когда метод возвращает, указывает, был ли вызывающий поток предоставлен первоначальное владение мьютексом. |
| Mutex(Boolean, String, NamedWaitHandleOptions, Boolean) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом, строка, представляющая имя мьютекса, параметры для задания доступа к области пользователя и области сеанса, а также логическое значение, которое, когда метод возвращает, указывает, был ли вызывающий поток предоставлен начальное владение мьютексом. |
| Mutex(Boolean, String, NamedWaitHandleOptions) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом, строкой, которая является именем мьютекса, а также параметрами для задания доступа к области пользователя и области сеанса. |
| Mutex(Boolean, String) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом и строку, которая является именем мьютекса. |
| Mutex(Boolean) |
Инициализирует новый экземпляр Mutex класса с логическим значением, указывающим, должен ли вызывающий поток иметь начальное владение мьютексом. |
| Mutex(String, NamedWaitHandleOptions) |
Инициализирует новый экземпляр Mutex класса строкой, которая является именем мьютекса и параметров для задания доступа к области сеанса и области пользователя. Вызывающий поток не запрашивает начальное владение мьютексом. |
Поля
| Имя | Описание |
|---|---|
| WaitTimeout |
Указывает, что операция истекла до того, WaitAny(WaitHandle[], Int32, Boolean) как любой из дескрипторов ожидания был сигналирован. Это поле является константой. (Унаследовано от WaitHandle) |
Свойства
| Имя | Описание |
|---|---|
| Handle |
Устаревшие..
Устаревшие..
Возвращает или задает дескриптор собственной операционной системы. (Унаследовано от WaitHandle) |
| SafeWaitHandle |
Возвращает или задает дескриптор собственной операционной системы. (Унаследовано от WaitHandle) |
Методы
| Имя | Описание |
|---|---|
| Close() |
Освобождает все ресурсы, удерживаемые текущим WaitHandle. (Унаследовано от WaitHandle) |
| CreateObjRef(Type) |
Создает объект, содержащий все соответствующие сведения, необходимые для создания прокси-сервера, используемого для взаимодействия с удаленным объектом. (Унаследовано от MarshalByRefObject) |
| Dispose() |
Освобождает все ресурсы, используемые текущим экземпляром класса WaitHandle. (Унаследовано от WaitHandle) |
| Dispose(Boolean) |
При переопределении в производном классе освобождает неуправляемые ресурсы, используемые и WaitHandleпри необходимости освобождает управляемые ресурсы. (Унаследовано от WaitHandle) |
| Equals(Object) |
Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object) |
| GetAccessControl() |
MutexSecurity Возвращает объект, представляющий безопасность управления доступом для именованного мьютекса. |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetLifetimeService() |
Устаревшие..
Извлекает текущий объект службы времени существования, который управляет политикой времени существования для этого экземпляра. (Унаследовано от MarshalByRefObject) |
| GetType() |
Возвращает Type текущего экземпляра. (Унаследовано от Object) |
| InitializeLifetimeService() |
Устаревшие..
Получает объект службы времени существования для управления политикой времени существования для этого экземпляра. (Унаследовано от MarshalByRefObject) |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| MemberwiseClone(Boolean) |
Создает неглубокую копию текущего MarshalByRefObject объекта. (Унаследовано от MarshalByRefObject) |
| OpenExisting(String, MutexRights) |
Открывает указанный именованный мьютекс, если он уже существует, с требуемым доступом к безопасности. |
| OpenExisting(String, NamedWaitHandleOptions) |
Открывает указанный именованный мьютекс, если он уже существует. Если параметры заданы только для текущего пользователя, элементы управления доступом объекта проверяются для вызывающего пользователя. |
| OpenExisting(String) |
Открывает указанный именованный мьютекс, если он уже существует. |
| ReleaseMutex() |
Mutex Освобождает один раз. |
| SetAccessControl(MutexSecurity) |
Задает безопасность управления доступом для именованного системного мьютекса. |
| ToString() |
Возвращает строку, представляющую текущий объект. (Унаследовано от Object) |
| TryOpenExisting(String, Mutex) |
Открывает указанный именованный мьютекс, если он уже существует, и возвращает значение, указывающее, выполнена ли операция успешно. |
| TryOpenExisting(String, MutexRights, Mutex) |
Открывает указанный именованный мьютекс, если он уже существует, при требуемом доступе к безопасности и возвращает значение, указывающее, выполнена ли операция успешно. |
| TryOpenExisting(String, NamedWaitHandleOptions, Mutex) |
Открывает указанный именованный мьютекс, если он уже существует, и возвращает значение, указывающее, выполнена ли операция успешно. Если параметры заданы только для текущего пользователя, элементы управления доступом объекта проверяются для вызывающего пользователя. |
| WaitOne() |
Блокирует текущий поток, пока текущий WaitHandle не получит сигнал. (Унаследовано от WaitHandle) |
| WaitOne(Int32, Boolean) |
Блокирует текущий поток, пока текущий WaitHandle не получит сигнал, используя 32-разрядное целое число со знаком, чтобы указать интервал времени и указать, следует ли выйти из домена синхронизации перед ожиданием. (Унаследовано от WaitHandle) |
| WaitOne(Int32) |
Блокирует текущий поток, пока текущий WaitHandle не получит сигнал, используя 32-разрядное целое число со знаком, чтобы указать интервал времени в миллисекундах. (Унаследовано от WaitHandle) |
| WaitOne(TimeSpan, Boolean) |
Блокирует текущий поток, пока текущий экземпляр не получит сигнал, используя TimeSpan интервал времени и указав, следует ли выйти из домена синхронизации перед ожиданием. (Унаследовано от WaitHandle) |
| WaitOne(TimeSpan) |
Блокирует текущий поток, пока текущий экземпляр не получит сигнал, используя TimeSpan интервал времени. (Унаследовано от WaitHandle) |
Явные реализации интерфейса
| Имя | Описание |
|---|---|
| IDisposable.Dispose() |
Этот API поддерживает инфраструктуру продукта и не предназначен для использования непосредственно из программного кода. Освобождает все ресурсы, используемые параметром WaitHandle. (Унаследовано от WaitHandle) |
Методы расширения
| Имя | Описание |
|---|---|
| GetAccessControl(Mutex) |
Возвращает дескрипторы безопасности для указанного |
| GetSafeWaitHandle(WaitHandle) |
Возвращает безопасный дескриптор для собственного дескриптора ожидания операционной системы. |
| SetAccessControl(Mutex, MutexSecurity) |
Задает дескрипторы безопасности для указанного мьютекса. |
| SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Задает безопасный дескриптор для собственного дескриптора ожидания операционной системы. |
Применяется к
Потокобезопасность
Этот тип является потокобезопасной.