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



Получить доступ к общему ресурсу.

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

 

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

В приведенном ниже примере программы описанный выше механизм синхронизации демонстрируется на практике. В этой программе создаются два потока в виде классов IncThread и 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 mt1 = new IncThread("Инкрементирующий Поток", 5);

Thread.Sleep(1); // разрешить инкрементирующему потоку начаться

DecThread mt2 = new DecThread("Декрементирующий Поток", 5);

 

mt1.Thrd.Join();

mt2.Thrd.Join();

}

}

 

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

 

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

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

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

В потоке Инкрементирующий Поток, SharedRes.Count = 1

В потоке Инкрементирующий Поток, SharedRes.Count = 2

В потоке Инкрементирующий Поток, SharedRes.Count = 3

В потоке Инкрементирующий Поток, SharedRes.Count = 4

В потоке Инкрементирующий Поток, SharedRes.Count = 5

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

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

В потоке Декрементирующий Поток, SharedRes.Count = 4

В потоке Декрементирующий Поток, SharedRes.Count = 3

В потоке Декрементирующий Поток, SharedRes.Count = 2

В потоке Декрементирующий Поток, SharedRes.Count = 1

В потоке Декрементирующий Поток, SharedRes.Count = 0

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

 

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

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

 


Дата добавления: 2019-02-12; просмотров: 234; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!