Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
14
Добавлен:
27.03.2016
Размер:
36.86 Кб
Скачать

Лабораторна робота N 7

Тема:

Синхронизація потоків. Використання семафорів.

Теоретичні відомості:

Semaphore

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

Semaphore с емкостью, равной единице, подобен Mutex или lock, за исключением того, что он не имеет потока-хозяина. Любой поток может вызвать Release для Semaphore, в то время как в случае с Mutex или lock только поток, захвативший ресурс, может его освободить.

В следующем примере по очереди запускаются десять потоков, выполняющих вызов Sleep. Semaphore гарантирует, что не более трех потоков могут вызвать Sleep одновременно:

class SemaphoreTest

{

static Semaphore s = new Semaphore(3, 3); // Available=3; Capacity=3

static void Main()

{

for (int i = 0; i < 10; i++)

new Thread(Go).Start();

}

static void Go()

{

while (true)

{

s.WaitOne();

// Только 3 потока могут находиться здесь одновременно

Thread.Sleep(100);

s.Release();

}

}

}

WaitAny, WaitAll и SignalAndWait

Кроме Set и WaitOne, есть еще несколько статических методов класса WaitHandle для более крепких орешков синхронизации.

Методы WaitAny, WaitAll и SignalAndWait облегчают взаимодействие нескольких WaitHandle, возможно разных типов.

SignalAndWait, возможно, самый полезный метод – он в рамках единой атомарной операции вызывает WaitOne для одного WaitHandle, и Set – для другого.

Классическим вариантом использования этого метода является использование с парой EventWaitHandle для подготовки встречи двух потоков в нужной точке в нужное время. Подойдут и AutoResetEvent и ManualResetEvent. Первый поток делает следующее:

WaitHandle.SignalAndWait(wh1, wh2);

в то время как второй поток – наоборот:

WaitHandle.SignalAndWait(wh2, wh1);

WaitHandle.WaitAny ожидает освобождения одного (любого) WaitHandle из переданного ему списка, WaitHandle.WaitAll ожидает освобождения сразу всех переданных ему WaitHandle. Используя аналогию с турникетом метро, эти методы организуют общую очередь одновременно для всех турникетов – с прохождением через первый открывшийся турникет (WaitAny) или с ожиданием, пока они не откроются все (WaitAll).

На самом деле, значение WaitAll сомнительно из-за странной связи с потоковыми апартаментами, унаследованными от COM-архитектуры. WaitAll требует, чтобы вызывающий поток находился в многопоточном апартаменте, в то время как эта модель может быть наименее подходящей, особенно для приложений Windows Forms, которые должны выполнять столь мирские задачи, как взаимодействие с буфером обмена.

К счастью, .NET Framework обеспечивает более продвинутый сигнальный механизм для случаев, когда WaitHandle являются неудобными или неподходящими – Monitor.Wait и Monitor.Pulse.

Завдання:

Скласти програму, в якій запустити 2 процеси з 2-ма потоками в кожному, в кожному процесі задати 2 масиви по 100 цілих чисел і заповнити їх довільними числами. Відкрити в одному потоці 2 текстових файли, ініціалізувати семафор, виконати запис елементів масивів в файли за наступним алгоритмом. Потоки 1/1 (№ процесу/№ потоку) та 1/2 захоплюють і блокують семафор заносять по 25 перших елементів своїх масивів в файл 1, а 25 наступних в файл 2, потім розблоковують семафор, потік 2/1 та 2/2 захоплюють семафор і виконують те саме. Повторити операцію поки всі елементи масивів не будуть передані в файл.

Соседние файлы в папке Semestr2