Объясните отличия между механизмами блокировки: lock, Semaphore и Mutex.
Ответ от нейросети
sobes.tech AI
Что хотят услышать интервьюеры:
lock — это самый простой способ сделать критическую секцию в C#: он гарантирует, что код внутри выполнит только один поток одновременно. Mutex и Semaphore — более низкоуровневые примитивы синхронизации; Mutex обычно нужен для взаимного исключения, в том числе между процессами, а Semaphore — для ограничения числа одновременно работающих потоков. Важно понимать не только назначение, но и стоимость: lock обычно легче и быстрее, чем Mutex.
Определение:
lock — это синтаксический сахар над монитором (Monitor) в C#, который защищает участок кода от одновременного доступа несколькими потоками внутри одного процесса.
Mutex — это объект взаимного исключения, который может синхронизировать доступ как внутри одного процесса, так и между процессами. В каждый момент времени владельцем может быть только один поток.
Semaphore — это счётчик разрешений. Он позволяет одновременно войти в критическую секцию не одному, а ограниченному числу потоков. Когда разрешения заканчиваются, остальные потоки ждут.
Пример использования:
using System;
using System.Threading;
class Program
{
private static readonly object _lockObj = new object();
private static int _counter = 0;
private static readonly Mutex _mutex = new Mutex();
private static readonly Semaphore _semaphore = new Semaphore(2, 2);
static void Main()
{
// lock: только один поток внутри критической секции
lock (_lockObj)
{
_counter++;
}
// Mutex: взаимное исключение, можно использовать между процессами
_mutex.WaitOne();
try
{
_counter++;
}
finally
{
_mutex.ReleaseMutex();
}
// Semaphore: одновременно не более 2 потоков
_semaphore.WaitOne();
try
{
Console.WriteLine("Поток вошёл в ограниченную секцию");
}
finally
{
_semaphore.Release();
}
}
}
Пояснение кода:
lock (_lockObj)защищает изменение_counterтак, чтобы в этот блок одновременно вошёл только один поток.Mutexтребует явного захвата черезWaitOne()и освобождения черезReleaseMutex(). Если не освободить вfinally, можно получить зависание.Semaphore(2, 2)означает, что одновременно в секцию могут войти максимум 2 потока.- Для
Semaphoreпосле работы обязательно вызываетсяRelease(), иначе разрешение не вернётся в счётчик. - На практике
lockчаще всего используют для синхронизации внутри приложения, аMutex— когда нужна межпроцессная синхронизация,Semaphore— когда нужен лимит параллелизма.
Ключевые моменты:
lock— самый удобный и распространённый вариант для синхронизации внутри одного процесса.Mutex— взаимное исключение с возможностью межпроцессной синхронизации, обычно тяжелееlock.Semaphore— не “один владелец”, а ограничение количества одновременных входов.- Для коротких критических секций обычно выбирают
lock. - Любой из этих механизмов нужно освобождать корректно, иначе легко получить дедлок или утечку разрешений.
- Нельзя использовать их как замену друг другу без понимания задачи: выбор зависит от того, нужен один поток, несколько потоков или синхронизация между процессами.