Поиск

Синхронизация кода с помощью класса Mutex

Класс Mutex, определенный в пространстве имен System. Threading, — это представление примитива системы Win32 с тем же именем для периода выполнения. Вы можете использовать мыотекс для упорядочивания обращений к коду так же, как блокировку монитора, но мьютексы намного медленнее из-за своей универсальности. Термин мыотекс (mutex) происходит от фразы mutually exclusive (взаимно исключающий), и поскольку только один поток может получить блокировку монитора для данного объекта в любой момент времени, только один поток в любой момент времени может получить данный мьютекс.

Три конструктора позволяют создавать мьютексы на С#:

Mutex();
Mutex(bool изначально_6локированный);
Mutex(bool изначально_блокированный, string имя_мьютекса).

Первый создает безымянный мьютекс и делает текущий поток его владельцем, поэтому мьютекс блокируется текущим потоком. Второй принимает только логический флаг, который определяет, собирается ли создающий мьютекс поток завладеть им (заблокировать его). Третий же позволяет указывать, владеет ли текущий поток мьютексом, а также задавать имя мьютекса. А теперь применим мьютекс для упорядочивания обращений к методу Database.SaveData'.

using System;
using System.Threading;
class Database {
Mutex mutex = new Mutex(false);
public void SaveData(string text)
{
mutex.WaitOne();
Console.WriteLine("Database.SaveData - Started");
Console.WriteLineC'Database.SaveData -
Working"); for (int i = 0; i < 100; i++)
{
Console.Write(text);
}
Console.WriteLine("\nDatabase.SaveData - Ended");
mutex.CloseO; } }
class ThreadMutexApp {
public static Database db = new DatabaseO;
public static void WorkerThreadMethodK) {
Console.WriteLineC"Worker thread #1 - Started");
Console.WrlteLine
("Worker thread #1 - Calling Database.SaveData"); db. SaveDataC'x");
Console.WriteLineC'Worker thread #1 - Returned from Output"); }
public static void WorkerThreadMethod2() {
Console.WriteLineC'Worker thread #2 - Started");
Console.WriteLine
("Worker thread #2 - Calling Database.SaveData"); db.SaveData("o");
Console.WriteLineC'Worker thread 92 - Returned from Output");
}
public static void Main() {
ThreadStart worker! = new ThreadStart(WorkerThreadMethodl);
ThreadStart worker2 = new ThreadStart(WorkerThreadMethod2);
Console.WriteLine("Main - Creating worker threads");
Thread t1 = new Thread(workeM); Thread t2 = new Thread(worker2);
t1.Start(); t2.Start(); > }

Теперь в классе Database определено поле Mutex. Мы не хотим, чтобы поток владел мыотексом просто потому, что при этом будет невозможно обратиться к методу SaveData. Первая строка метода SaveData показывает, что вы должны пытаться получить мьютекс с помощью метода Mutex. WaitOne. В конце метода вызывается метод Close, освобождающий мьютекс.
Метод WaitOne перегружен чтобы обеспечить большую гибкость в предоставлении вам возможности определения, сколь долго поток будет ждать освобождения мьютекса. Вот как он перегружается:

WaitOne()

WaitOne(TimeSpan время, bool покину>ть_контекст) WaitOne(int миллисекунды, bool покинуть_контекст) Основное различие между этими способами перегрузки в том, что первая версия (она использована в примере) будет ждать неопределенно долго, а вторая и третья будут ждать в течение указанного промежутка времени, выраженного значением типа TimeSpan или int.