SemaphoreSlim в C#
Класс SemaphoreSlim считает, сколько потоков одновременно могут войти в секцию. Wait уменьшает счётчик (и блокируется при нуле), Release возвращает слот. Так ограничивают доступ к пулу соединений или тяжёлым ресурсам.
Release вызывают в finally. Иначе слот не вернётся, и остальные потоки зависнут на входе.
Два слота и три потока: одновременно внутри секции не больше двух. Третий ждал, пока один из первых не вышел и не вернул слот. Если бы в конструкторе был один слот, максимум в консоли был бы 1:
using SemaphoreSlim sem = new(2, 2);
int concurrent = 0;
int maxSeen = 0;
object gate = new();
void Work()
{
sem.Wait();
try
{
lock (gate)
{
concurrent++;
maxSeen = Math.Max(maxSeen, concurrent);
}
Thread.Sleep(20);
lock (gate) concurrent--;
}
finally { sem.Release(); }
}
Thread[] workers = [new(Work), new(Work), new(Work)];
foreach (Thread t in workers) t.Start();
foreach (Thread t in workers) t.Join();
Console.WriteLine(maxSeen); // выведет 2
Разрешите только одному потоку быть внутри секции. Запустите четыре потока. В каждом войдите в секцию, отметьте вход и выйдите. Выведите, сколько потоков побывало внутри одновременно в пике.