Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Синхронизация на основе подачи сигналов






При использовании синхронизации на основе подачи сигналов один поток получает уведомления от другого потока. Обычно уведомления используются для возобновления работы заблокированного потока. Для реализации данного подхода платформа.NET предлагает классы AutoResetEvent, ManualResetEvent, ManualResetEventSlim, CountdownEvent и Barrier (все они размещены в пространстве имён System.Threading).

Классы AutoResetEvent, ManualResetEvent, ManualResetEventSlim унаследованы от класса EventWaitHandle. Имея доступ к объекту EventWaitHandle, поток может вызвать его метод WaitOne(), чтобы остановиться и ждать сигнала. Для отправки сигнала применяется вызов метода Set(). Если используются ManualResetEvent и ManualResetEventSlim, все ожидающие потоки освобождаются и продолжают выполнение. При использовании AutoResetEvent ожидающие потоки освобождаются и запускаются последовательно, на манер очереди. Аналогией для AutoResetEvent является турникет, пропускающий людей по одному, а ManualResetEvent подобен воротам, которые или закрыты, или открыты.

Рис. 18. Пример работы с объектом AutoResetEvent.

Класс CountdownEvent позволяет организовать счётчик уведомлений. Конструктор класса принимает в качестве аргумента начальное значение счётчика. Вызов экземплярного метода Signal() уменьшает значение счётчика на единицу. Метод Wait() блокирует поток, пока счётчик не станет равным нулю.

private static CountdownEvent counter = new CountdownEvent(3);

 

public static void Main()

{

new Thread(SaySomething).Start(" I am thread 1");

new Thread(SaySomething).Start(" I am thread 2");

new Thread(SaySomething).Start(" I am thread 3");

 

// ждём, пока метод Signal() не вызовется три раза

counter.Wait();

Console.WriteLine(" All threads have finished speaking! ");

}

 

private static void SaySomething(object thing)

{

Thread.Sleep(1000);

Console.WriteLine(thing);

counter.Signal();

}

Объект класса Barrier организует для нескольких потоков точку встречи во времени. Чтобы использовать Barrier, нужно вызвать его конструктор, передав количество встречающихся потоков. Затем отдельные потоки вызывают экземплярный метод Barrier.SignalAndWait(), чтобы приостановиться и продолжить выполнение после совместной встречи.

В следующем примере каждый из трёх потоков печатает числа от 0 до 4, синхронизируя работу со своими «коллегами»:

using System;

using System.Threading;

 

public class BarrierExample

{

private static readonly Barrier _barrier = new Barrier(3);

 

public static void Main()

{

new Thread(Speak).Start();

new Thread(Speak).Start();

new Thread(Speak).Start();

// вывод: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4

 

Console.ReadLine();

}

 

private static void Speak()

{

for (var i = 0; i < 5; i++)

{

Console.Write(i + " ");

_barrier.SignalAndWait();

}

}

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.