Страница 412 из 502
<b> // Точка входа в поток,</b>
<b> void Run() {</b>
<b> Console.WriteLine(Thrd.Name + " ожидает мьютекс.");</b>
<b> // Получить мьютекс.</b>
<b> SharedRes.Mtx.WaitOne();</b>
<b> Console.WriteLine(Thrd.Name + " получает мьютекс.");</b>
<b> do {</b>
<b> Thread.Sleep(500) ;</b>
<b> SharedRes.Count--;</b>
<b> Console.WriteLine("В потоке " + Thrd.Name +</b>
<b> ", SharedRes.Count = " + SharedRes.Count);</b>
<b> num-- ;</b>
<b> } while(num > 0);</b>
<b> Console.WriteLine(Thrd.Name + " освобождает мьютекс.");</b>
<b> // Освободить мьютекс.</b>
<b> SharedRes.Mtx.ReleaseMutex();</b>
<b> }</b>
<b>}</b>
<b>class MutexDemo {</b>
<b> static void Main() {</b>
<b> // Сконструировать два потока.</b>
<b> IncThread mt1 = new IncThread("Инкрементирующий Поток", 5);</b>
<b> Thread.Sleep(1); // разрешить инкрементирующему потоку начаться</b>
<b> DecThread mt2 = new DecThread("Декрементирующий Поток", 5);</b>
<b> mt1.Thrd.Join();</b>
<b> mt2.Thrd.Join();</b>
<b> }</b>
<b>}</b>
Эта программа дает следующий результат.
<b>Инкрементирующий Поток ожидает мьютекс.</b>
<b>Инкрементирующий Поток получает мьютекс.</b>
<b>Декрементирующий Поток ожидает мьютекс.</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 2</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 3</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 4</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 5</b>
<b>Инкрементирующий Поток освобождает мьютекс.</b>
<b>Декрементирующий Поток получает мьютекс.</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 4</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 3</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 2</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>Декрементирующий Поток освобождает мьютекс.</b>
Как следует из приведенного выше результата, доступ к общему ресурсу (переменной SharedRes.Count) синхронизирован, и поэтому значение данной переменной может быть одновременно изменено только в одном потоке.
Для того чтобы убедиться в том, что мьютекс необходим для получения приведенного выше результата, попробуйте закомментировать вызовы методов WaitOne() и ReleaseMutex() в исходном коде рассматриваемой здесь программы. При ее последующем выполнении вы получите следующий результат, хотя у вас он может оказаться несколько иным.
<b>Инкрементирующий Поток ожидает мьютекс.</b>
<b>Инкрементирующий Поток получает мьютекс.</b>
<b>Декрементирующий Поток ожидает мьютекс.</b>
<b>Декрементирующий Поток получает мьютекс.</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>В потоке Инкрементирующий Поток, SharedRes.Count = 1</b>
<b>Инкрементирующий Поток освобождает мьютекс.</b>
<b>В потоке Декрементирующий Поток, SharedRes.Count = 0</b>
<b>Декрементирующий Поток освобождает мьютекс.</b>
Как следует из приведенного выше результата, без мьютекса инкрементирование и декрементирование переменной SharedRes.Count происходит, скорее, беспорядочно, чем последовательно.
Мьютекс, созданный в предыдущем примере, известен только тому процессу, который его породил. Но мьютекс можно создать и таким образом, чтобы он был известен где-нибудь еще. Для этого он должен быть именованным. Ниже приведены формы конструктора, предназначенные для создания такого мьютекса.