872
Глава.30 .Гибридные.конструкции.синхронизации.потоков
public Boolean Signal(Int32 signalCount); // Уменьшение CurrentCount
// на signameCount
public Boolean Wait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
public Int32 CurrentCount { get; }
public Boolean IsSet { get; } // true, если
// CurrentCount равно 0
public WaitHandle WaitHandle { get; }
}
Достигнутое параметром
CurrentCount
класса
CountdownEvent
нулевое значение
уже не может быть изменено. Если параметр
CurrentCount
равен 0,
метод
AddCount
генерирует исключение
InvalidOperationException
, а метод
TryAddCount
просто
возвращает значение
false
.
Класс Barrier
Конструкция
System.Threading.Barrier
была создана
для решения достаточно
редко возникающей проблемы, так что вряд ли вам когда-нибудь придется ею
пользоваться. Она управляет группами параллельно выполняющихся потоков,
обеспечивая одновременное прохождение ими всех фаз алгоритма. К примеру,
когда CLR задействует серверную
версию уборщика мусора, его алгоритм создает
один поток исполнения для каждого ядра. Эти потоки проходят через различные
стеки приложения, одновременно помечая объекты в куче. Завершив свою порцию
работы, поток должен остановиться и подождать завершения работы остальных.
Когда
все потоки пометят объекты, они смогут одновременно приступить к сжатию
различных частей кучи. Поток, закончивший сжимать кучу, следует заблокировать,
чтобы он дождался завершения остальных потоков. Потом все потоки одновре-
менно пройдут через стек потоков приложения,
присваивая корням ссылки на
новые местоположения сжатых объектов. И только после завершения всех потоков
деятельность сборщика мусора считается оконченной и появляется возможность
восстановить поток приложения.
Данный сценарий легко реализуется при помощи класса
Barrier
, который
выглядит следующим образом (некоторые перегруженные
версии методов не по-
казаны):
public class Barrier : IDisposable {
public Barrier(Int32 participantCount, Action
postPhaseAction);
public void Dispose();
public Int64 AddParticipants(Int32 participantCount); // Добавление
// участников
public void RemoveParticipants(Int32 participantCount); // Удаление
// участников
public Boolean SignalAndWait(
Int32 millisecondsTimeout, CancellationToken cancellationToken);
public Int64 CurrentPhaseNumber { get; } // Показывает фазы процесса
873
Гибридные.конструкции.в.FCL
// (начиная с 0)
public Int32 ParticipantCount { get; } // Количество участников
public Int32 ParticipantsRemaining { get; } // Число потоков, необходимых
// для вызова SignalAndWait
}
При конструировании класса
Barrier
указывается количество потоков, ко-
торые будут принимать участие в работе. Можно также передать конструктору
делегата
Action
, ссылающегося на код, который будет вызван после
завершения всеми участниками очередной фазы. Динамически добавлять потоки
к классу
Barrier
и удалять их оттуда можно при помощи методов
AddParticipant
и
RemoveParticipant
, но на практике это делается крайне редко. Завершивший
свою фазу работы поток должен вызвать метод
SignalAndWait
, который за-
ставит метод
Barrier
заблокировать данный поток (с помощью конструкции
ManualResetEventSlim
). После вызова метода
SignalAndWait
всеми участниками
метод
Barrier
вызывает делегата (с помощью последнего обращавшегося к методу
SignalAndWait
потока) и снимает блокировку со всех потоков, давая им возмож-
ность перейти к следующей фазе.
Do'stlaringiz bilan baham: