Когда же в коде больше не требуется владеть мьютексом, он освобождается посредством вызова метода ReleaseMutex () , форма которого приведена ниже.

Public void ReleaseMutex()

В этой форме метод ReleaseMutex () освобождает мьютекс, для которого он был вызван, что дает возможность другому потоку получить данный мьютекс.

Для применения мьютекса с целью синхронизировать доступ к общему ресурсу упомянутые выше методы WaitOne () и ReleaseMutex () используются так, как показано в приведенном ниже фрагменте кода.

Mutex myMtx = new Mutex();

// ...

myMtx.WaitOne() ; // ожидать получения мьютекса // Получить доступ к общему ресурсу.

myMtx.ReleaseMutex(); // освободить мьютекс

При вызове метода WaitOne () выполнение соответствующего потока приостанавливается до тех пор, пока не будет получен мьютекс. А при вызове метода ReleaseMutex () мьютекс освобождается и затем может быть получен другим потоком. Благодаря такому подходу к синхронизации одновременный доступ к общему ресурсу ограничивается только одним потоком.

В приведенном ниже примере программы описанный выше механизм синхронизации демонстрируется на практике. В этой программе создаются два потока в виде классов IncThreadn DecThread, которым требуется доступ к общему ресурсу: переменной SharedRes . Count. В потоке IncThread переменная SharedRes . Count инкрементируется, а в потоке DecThread — декрементируется. Во избежание одновременного доступа обоих потоков к общему ресурсу SharedRes . Count этот доступ синхронизируется мьютексом Mtx, также являющимся членом класса SharedRes.

// Применить мьютекс.

Using System;

Using System.Threading;

//В этом классе содержится общий ресурс(переменная Count),

// а также мьютекс (Mtx), управляющий доступом к ней. class SharedRes {

public static int Count = 0;

public static Mutex Mtx = new Mutex();

}

// В этом потоке переменная SharedRes.Count инкрементируется, class IncThread { int num;

Public Thread Thrd;

public IncThread(string name, int n) {

Thrd = new Thread(this.Run); num = n;

Thrd.Name = name;

Thrd.Start();

}

// Точка входа в поток, void Run() {

Console.WriteLine(Thrd.Name + " ожидает мьютекс.");

// Получить мьютекс.

SharedRes.Mtx.WaitOne();

Console.WriteLine(Thrd.Name + " получает мьютекс."); do {

Thread.Sleep (500);

SharedRes.Count++;

Console.WriteLine("В потоке " + Thrd.Name +

", SharedRes.Count = " + SharedRes.Count);

Num— ;

} while(num > 0);

Console.WriteLine(Thrd.Name + " освобождает мьютекс.");

// Освободить мьютекс.

SharedRes.Mtx.ReleaseMutex();

}

}

// В этом потоке переменная SharedRes.Count декрементируется, class DecThread { int num;

Public Thread Thrd;

public DecThread(string name, int n) {

Thrd = new Thread(new ThreadStart(this.Run)); num = n;

Thrd.Name = name;

Thrd.Start();

}

// Точка входа в поток, void Run() {

Console.WriteLine(Thrd.Name + " ожидает мьютекс.");

// Получить мьютекс.

SharedRes.Mtx.WaitOne();

Console.WriteLine(Thrd.Name + " получает мьютекс."); do {

Thread.Sleep(500) ;

SharedRes.Count—;

Console.WriteLine("В потоке " + Thrd.Name +

", SharedRes.Count = " + SharedRes.Count);

Num— ;

} while(num > 0);

Console.WriteLine(Thrd.Name + " освобождает мьютекс.");

// Освободить мьютекс.

SharedRes.Mtx.ReleaseMutex();

}

}

class MutexDemo {

static void Main() {

// Сконструировать два потока.

IncThread mtl = new IncThread("Инкрементирующий Поток", 5); Thread.Sleep(1); // разрешить инкрементирующему потоку начаться DecThread mt2 = new DecThread("Декрементирующий Поток", 5);

Mtl.Thrd.Join();

Mt2.Thrd.Join();

}

}

Эта программа дает следующий результат.

Инкрементирующий Поток ожидает мьютекс.

Инкрементирующий Поток получает мьютекс.

Декрементирующий Поток ожидает мьютекс.

Декрементирующий Поток освобождает мьютекс.

Как следует из приведенного выше результата, доступ к общему ресурсу (переменной SharedRes . Count) синхронизирован, и поэтому значение данной переменной может быть одновременно изменено только в одном потоке.

Для того чтобы убедиться в том, что мьютекс необходим для получения приведенного выше результата, попробуйте закомментировать вызовы методов WaitOne () и ReleaseMutex () в исходном коде рассматриваемой здесь программы. При ее последующем выполнении вы получите следующий результат, хотя у вас он может оказаться несколько иным.

Наши рекомендации