🖥
Факт дня — семафоры в C#Семафоры позволяют ограничить количество потоков, которые имеют доступ к определенным ресурсам. В .NET семафоры представлены классом
Semaphore.
Для создания семафора применяется один из конструкторов класса
Semaphore:
🟡
Semaphore (int initialCount, int maximumCount) параметр
initialCount задает начальное количество потоков, а
maximumCount — максимальное количество потоков, которые имеют доступ к общим ресурсам:
initialCount — изначальное доступное количество свободных мест,
maximumCount — вместимость.
🟡
Semaphore (int initialCount, int maximumCount, string? name) в дополнение задает имя семафора
🟡
Semaphore (int initialCount, int maximumCount, string? name, out bool createdNew): последний параметр —
createdNew при значении
true указывает, что новый семафор был успешно создан. Если этот параметр равен
false, то семафор с указанным именем уже существует
Для работы с потоками класс
Semaphore имеет 2 основных метода:
—
WaitOne() ожидает получения свободного места в семафоре
—
Release() освобождает место в семафоре
В отличие от
lock (Monitor) и
Mutex, у
Semaphore нет «владельца» — он не зависит от потока. Любой поток может вызвать
Release на семафоре, тогда как с
Mutex и блокировкой только поток, получивший блокировку, может ее освободить.
// запускаем пять потоков
for (int i = 1; i < 6; i++)
{
Reader reader = new Reader(i);
}
class Reader
{
// создаем семафор
static Semaphore sem = new Semaphore(3, 3);
Thread myThread;
int count = 3;// счетчик чтения
public Reader(int i)
{
myThread = new Thread(Read);
myThread.Name = $"Читатель {i}";
myThread.Start();
}
public void Read()
{
while (count > 0)
{
sem.WaitOne(); // ожидаем, когда освободиться место
Console.WriteLine($"{Thread.CurrentThread.Name} входит в библиотеку");
Console.WriteLine($"{Thread.CurrentThread.Name} читает");
Thread.Sleep(1000);
Console.WriteLine($"{Thread.CurrentThread.Name} покидает библиотеку");
sem.Release(); // освобождаем место
count--;
Thread.Sleep(1000);
}
}
}
@csharp_ci