Можешь перечислить основные примитивы синхронизации, предоставляемые стандартной библиотекой?
Ответ от нейросети
sobes.tech AI
Что хотят услышать интервьюеры:
В стандартной библиотеке C# есть несколько базовых примитивов для синхронизации потоков и координации доступа к общим данным. Чаще всего ожидают услышать про lock/Monitor, Mutex, Semaphore/SemaphoreSlim, ReaderWriterLockSlim, AutoResetEvent и ManualResetEventSlim. Важно понимать, что они решают разные задачи: взаимное исключение, ограничение числа одновременных операций, ожидание события и защиту чтения/записи.
Определение:
Примитивы синхронизации — это механизмы, которые помогают безопасно работать с разделяемыми ресурсами в многопоточном коде. Они предотвращают гонки данных, обеспечивают упорядочивание доступа и позволяют потокам ждать друг друга или внешнего события. В C# часть из них встроена в язык и платформу, часть предоставляется как классы в System.Threading.
Пример использования:
Например, если несколько потоков увеличивают общий счётчик, доступ к нему нужно защитить. Для этого обычно используют lock, а если нужно ограничить количество одновременно работающих потоков — SemaphoreSlim.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static readonly object _sync = new object();
private static int _counter = 0;
static async Task Main()
{
var tasks = new Task[5];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() =>
{
lock (_sync)
{
_counter++;
}
});
}
await Task.WhenAll(tasks);
Console.WriteLine(_counter);
}
}
Пояснение кода:
Код показывает защиту общего ресурса с помощью lock. Все потоки пытаются увеличить _counter, но одновременно критическую секцию может выполнить только один поток. Объект _sync используется как монитор для синхронизации, а сам инкремент вынесен внутрь защищённого блока, чтобы не возникло гонки данных.
Если бы задача была не в защите переменной, а в ограничении параллелизма, вместо lock подошёл бы SemaphoreSlim: он позволяет пропускать только заданное число потоков одновременно. Для ожидания сигнала от другого потока или события использовали бы AutoResetEvent или ManualResetEventSlim.
Ключевые моменты:
lock/Monitor— самый частый способ взаимного исключения для защиты критической секции.Mutexподходит для синхронизации между процессами, но обычно тяжелее, чемlock.Semaphore/SemaphoreSlimограничивают количество одновременно выполняемых операций.ReaderWriterLockSlimполезен, когда чтений много, а записей мало.AutoResetEventиManualResetEventSlimнужны для координации потоков через сигналы и ожидание событий.- Важно выбирать примитив по задаче: защита данных, ограничение параллелизма или ожидание сигнала — это разные сценарии.