27 Возможности библиотеки Task Parallel Library. Семафоры

Объект синхронизации Semaphore отличается от сигнальных событий наличием внутреннего счетчика с устанавливаемым максимальным значением. Объект AutoResetEvent можно интерпретировать как семафор с максимальным счетчиком равным 1 (двоичный семафор).


В следующем фрагменте рассматривается применение семафоров. В коде используется объект SemaphoreSlim. Вместо него можно использовать объект Semaphore.

// Применение семафоров 
class SemaphoreSlimTesting 
{ 
  private static SemaphoreSlim sem; 
  private static void Worker(object num) 
  { 
    // Ждем сигнала от управляющего 
    sem.Wait(); 
    // Начинаем работу 
    Console.WriteLine("Worker {0} starting", num); 
  } 
  private static void Main() 
  { 
    // Максимальная емкость семафора: 5 
    // Начальное состояние: 0 (все блокируются) 
    sem = new SemaphoreSlim(0, 5); 
    Thread[] workers = new Thread[10]; 
    for(int i=0; i<workers.Length; i++) 
    { 
      workers[i] = new Thread(Worker); 
      workers[i].Start(i); 
    } 
    Thread.Sleep(300); 
    Console.WriteLine("Разрешаем работу трем рабочим"); 
    sem.Release(3); 
    Thread.Sleep(200); 
    Console.WriteLine("Разрешаем работу еще двум рабочим"); 
    sem.Release(2); 

  } 
} 
  
В методе Main инициализируется семафор SemaphoreSlim. Начальное значение внутреннего счетчика равно 0, максимальное значение – 5. Рабочие потоки блокируются, так как счетчик семафора равен нулю. Главный поток увеличивает счетчик на три единицы, тем самым освобождая три потока. После небольшой паузы главный поток освобождает еще два потока.

Вывод программы:
Разрешаем работу трем рабочим 
Worker 9 starting 
Worker 6 starting 
Worker 0 starting 
Разрешаем работу еще двум рабочим 
Worker 8 starting 
Worker 1 starting