Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Синхронизация потоков
Класс Mutex
Когда двум или более потокам одновременно требуется доступ к общему ресурсу, системе необходим механизм синхронизации, чтобы обеспечить использование ресурса только одним потоком одновременно. Класс Mutex, определенный в пространстве имен System. Threading - это примитив, который предоставляет эксклюзивный доступ к общему ресурсу только одному потоку синхронизации. Если поток получает семафор, второй поток, желающий получить этот семафор, приостанавливается до тех пор, пока первый поток не освободит семафор. Термин Mutex происходит от фразы mutually exclusive (взаимно исключающий), и поскольку только один поток может получить блокировку монитора для данного объекта в любой момент времени, только один поток в любой момент времени может получить данный Mutex. Класс Mutex очень похож на класс Monitor тем, что тоже допускает наличие только одного владельца. Только один поток может получить блокировку и иметь доступ к защищаемым Mutex синхронизированным областям кода. У Mutex имеется несколько конструкторов. Ниже приведены три наиболее употребительных конструктора:
public Mutex() public Mutex(bool initiallyOwned); public Mutex(bool initiallyOwned, string name_mutex)
В первой форме конструктора создается Mutex, которым первоначально никто не владеет. А во второй и третей форме исходным состоянием Mutex завладевает вызывающий поток, если параметр initiallyOwned имеет логическое значение true, если false, то объектом Mutex никто не владеет.
Для того чтобы получить Mutex, используется метод WaitOne(). Метод WaitOne() ожидает до тех пор, пока не будет получен Mutex, для которого он был вызван. Следовательно, этот метод блокирует выполнение вызывающего потока до тех пор, пока не станет доступным указанный Mutex. Данный метод всегда возвращает логическое значение true. Форма объявления метода WaitOne():
Mutex mutex = new Mutex(false); mutex.WaitOne();
Когда в коде не требуется использовать Mutex, он освобождается с помощью метода ReleaseMutex():
mutex.ReleaseMutex();
Ниже продемонстрирован код реализующий работу Mutex:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Mutext { class Program { private static Mutex mut = new Mutex(); private const int numIterations = 1; private const int numThreads = 3; private static void Main(string[] args) { // Создаем потоки, которые будут использовать защищенный ресурс for (int i = 0; i < numThreads; i++) { Thread myThread = new Thread(new ThreadStart(MyThreadProc)); myThread.Name = String.Format("Поток{0}", i + 1); myThread.Start(); } // Главный поток завершил работу } private static void MyThreadProc() { for (int i = 0; i < numIterations; i++) { UseResource(); } } //Синхронизируем данный метод private static void UseResource() { mut.WaitOne(); Console.WriteLine("{0} зашел в защищенную зону", Thread.CurrentThread.Name); // Имитируем работу Thread.Sleep(500); Console.WriteLine("{0} покинул защищенную зону", Thread.CurrentThread.Name); // Release the Mutex. mut.ReleaseMutex(); Console.ReadLine(); } }}
Результат работы программы, с использованием Mutex, представлен на Рис. 5.5.
Если же закомментировать методы WaitOne() и ReleaseMutex() и запустить программу, то программа сгенерирует результат, представленный на Рис. 5.6.