} 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()
в исходном коде рассматриваемой здесь программы. При ее последующем выполнении вы получите следующий результат, хотя у вас он может оказаться несколько иным.
Инкрементирующий Поток ожидает мьютекс.
Инкрементирующий Поток получает мьютекс.
Декрементирующий Поток ожидает мьютекс.
Декрементирующий Поток получает мьютекс.
В потоке Инкрементирующий Поток, SharedRes.Count = 1
В потоке Декрементирующий Поток, SharedRes.Count = 0
В потоке Инкрементирующий Поток, SharedRes.Count = 1
В потоке Декрементирующий Поток, SharedRes.Count = 0
В потоке Инкрементирующий Поток, SharedRes.Count = 1
В потоке Декрементирующий Поток, SharedRes.Count = 0
В потоке Инкрементирующий Поток, SharedRes.Count = 1
В потоке Декрементирующий Поток, SharedRes.Count = 0
В потоке Инкрементирующий Поток, SharedRes.Count = 1
Инкрементирующий Поток освобождает мьютекс.
В потоке Декрементирующий Поток, SharedRes.Count = 0
Декрементирующий Поток освобождает мьютекс.
Как следует из приведенного выше результата, без мьютекса инкрементирование и декрементирование переменной SharedRes.Count
происходит, скорее, беспорядочно, чем последовательно.
Читать дальше