Как семафор освобождает от другого потока? - PullRequest
0 голосов
/ 28 января 2019

Из того, что я знаю, поток может освобождаться на семафоре без предварительного получения блокировки с помощью WaitOne.

Итак, если у нас есть потоки A, B и C и семафор, вызовы A и B WaitOne, получите замок и начните заниматься своими делами.Вдоль потока C и просто вызывает Release на семафор.

Это должно увеличить счет семафора на 1. Означает ли это, что семафор завершит или A или B, или просто позволит третьему потоку получить блокировкуи иметь 3 потока в своем пуле, даже если максимум был 2?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Рассмотрим

var semaphore = new SemaphoreSlim(2);

Это означает, что семафор в данный момент имеет только 2 слота выполнения, но вы должны иметь в виду, что это только начальное число слоты для выполнения (для одновременных запросов).

Итак, если мы создадим поток A, B, C в семафор с двумя слотами для выполнения, первые два потока будут выполнены, а поток C будет поставлен в очередьпока кто-то еще в коде не сообщит семафору, что это нормально, чтобы добавить еще один слот выполнения.

Когда кто-то скажет, что все в порядке, чтобы выполнить следующий поток в очереди, C будет выполняться независимо от другихthread.


Несколько технических примеров:

(как я видел в курсе @ dmitri-nesteruk)

Общее количество доступных казнейslots представляется как CurrentCount.

Каждый раз, когда поток хочет исполниться, он спрашивает семафор, есть ли у него доступный слот выполнения (с CurrentCount > 0), если true - не стесняйтесь получитьВыполните сами, если не попадете в очередь.

Что делает семафор настолько запутанным, так это то, что значение CurrentCount может быть уменьшено или увеличено.

  • Его значение уменьшается на единицу каждый раз, когда потоком вызывается Wait(), что означает, что имеется один менее доступный слот выполнения и выполняется поток.

  • Увеличивается на единицу (или более) каждый раз, когда Release(1) вызывается где-то еще в коде, что означает, что есть еще один доступный слот выполнения, поэтому первый поток внутри семафора внутри очередь выполняется (остальные не прекратятся).

В этом примере мы порождаем 3 потока, но только первые два будут выполняться докто-то скажет семафору, что он может освободить другой слот выполнения, увеличив CurrentCount на Release(1).

for (int i = 0; i < 3 ; i++)
{
    Task.Factory.StartNew(() => 
    {
        Console.WriteLine($"Spawning task: {Task.CurrentId}");
        semaphore.Wait(); //CurrentCount--
        Console.WriteLine($"Executing task: {Task.CurrentId}");
    });
}


while (semaphore.CurrentCount <= 2)
{
    Console.ReadKey();
    Console.WriteLine("Key pressed");
    semaphore.Release(1); //CurrentCount++
}

Выход:

Spawning task: A
Spawning task: B
Spawning task: C
Executing task: A
Executing task: B
.....
Key pressed
Executing task: C
0 голосов
/ 28 января 2019

Вы можете рассматривать семафор как особый случай блокировки очереди: «счетчик» семафора - это количество элементов в очереди, но сами элементы не содержат информации.Точно так же, как любому потоку разрешено помещать элемент в очередь блокировки, и любому потоку разрешается вынимать элемент, так что любой поток может увеличивать или уменьшать счет семафора.

...