Какие методы синхронного взаимодействия существуют и когда они применяются
Что проверяют
Умеете ли вы выбрать примитив синхронизации в .NET по задаче и знаете ли, какие из них совместимы с async/await. Если неясно, про потоки вопрос или про взаимодействие сервисов, уточните. Про потоки следом обычно спрашивают, почему внутри lock нельзя await и чем его заменить.
Как отвечать
Разложите инструменты по сценариям:
lock: взаимное исключение внутри процесса. Компилятор разворачивает его вMonitor.EnterиMonitor.Exitвtry/finally. В .NET 9 появился типSystem.Threading.Lock, и для объекта этого типа C# 13 генерирует вызовEnterScope(), это быстрее классическогоMonitor;Monitor: то же, плюсTryEnterс таймаутом иWait/Pulseдля ожидания условия;Interlocked: атомарныеIncrement,CompareExchangeбез блокировки. Для счётчиков и флагов дешевле любогоlock;SemaphoreSlim: ограничивает число параллельных участников и умеетWaitAsync, поэтому это обычная заменаlockв асинхронном коде;ReaderWriterLockSlim: много читателей или один писатель, для кешей с редкой записью;MutexиSemaphore: объекты ядра ОС, медленные. Нужны ради именованных версий и синхронизации между процессами, например чтобы запустить единственный экземпляр приложения;- координация:
ManualResetEventSlim,CountdownEvent,Barrier.
Добавьте, что синхронизацию часто лучше убрать совсем: ConcurrentDictionary, Channel<T> для схемы производитель и потребитель, неизменяемые данные.
Где спотыкаются
Пытаются написать await внутри lock. Это ошибка компиляции CS1996, а обход через ручной Monitor сломается: продолжение после await может выполниться в другом потоке, и Monitor.Exit бросит исключение.
Используют Mutex в асинхронном коде. Мьютекс принадлежит потоку, который его захватил, освободить его из другого потока нельзя.
Блокируются на this, typeof(...) или строке. Такой объект виден снаружи, и чужой код может взять ту же блокировку. Нужно приватное поле readonly object только для этой цели.