Ответ
В .NET lock — это ключевое слово языка C#, а Monitor — класс в пространстве имен System.Threading. lock является синтаксическим сахаром над методами Monitor.Enter и Monitor.Exit.
Lock (Синтаксический сахар)
lock автоматически создает блок try-finally, гарантируя освобождение блокировки даже при возникновении исключения.
private readonly object _syncObject = new object();
public void ThreadSafeMethod()
{
lock (_syncObject)
{
// Критическая секция. Доступен только одному потоку.
SharedResource.Count++;
}
}
Monitor (Более гибкий низкоуровневый API)
Класс Monitor предоставляет прямой контроль и дополнительные возможности, которых нет у lock.
private readonly object _syncObject = new object();
public void ThreadSafeMethod()
{
bool lockTaken = false;
try
{
Monitor.Enter(_syncObject, ref lockTaken); // Явный захват
// Критическая секция
SharedResource.Count++;
}
finally
{
if (lockTaken)
{
Monitor.Exit(_syncObject); // Явное освобождение
}
}
}
Ключевые различия
- Удобство и безопасность:
lockпроще и безопаснее, так как компилятор сам генерирует корректный код освобождения вfinally. - Гибкость:
Monitorпредоставляет методы для сложных сценариев синхронизации:Monitor.Wait(object obj): Временно освобождает блокировку и ожидает сигнала.Monitor.Pulse(object obj)иMonitor.PulseAll(object obj): Уведомляют один или все ожидающие потоки.Monitor.TryEnter(object obj, int millisecondsTimeout): Пытается захватить блокировку с таймаутом, что помогает избежать взаимных блокировок (deadlock).
Вывод: Используйте lock для простых критических секций. Прибегайте к Monitor напрямую, когда нужны таймауты (TryEnter) или сложные шаблоны взаимодействия потоков, такие как Producer-Consumer.
Ответ 18+ 🔞
Ну слушай, раз уж зашла речь про многопоточность в .NET, давай разберём эту парочку — lock и Monitor. Это ж как два брата: один прилизанный, в костюмчике, а второй — в трениках, но с полным арсеналом фишек в карманах.
Вот смотри, lock в C# — это такая удобная обёртка, синтаксический сахар, блядь. Компилятор за тебя всю грязную работу делает. Написал lock(_syncObject) — и всё, ты как будто в безопасной комнате: один вошёл, дверь закрылась, остальные ждут снаружи. А главное — даже если внутри исключение выскочит, эта штука сама блокировку отпустит. Красота!
private readonly object _syncObject = new object();
public void ThreadSafeMethod()
{
lock (_syncObject)
{
// Сиди тут, работай. Пока один не выйдет, другие не сунутся.
SharedResource.Count++;
}
}
А теперь снимаем розовые очки. Под капотом-то этот lock — просто вызов методов класса Monitor. И если тебе мало просто захватить и отпустить, если хочется поизвращаться — вот он, голый API, бери и пользуйся.
private readonly object _syncObject = new object();
public void ThreadSafeMethod()
{
bool lockTaken = false; // Флажок, что захватил. А то мало ли что.
try
{
Monitor.Enter(_syncObject, ref lockTaken); // Пытаемся войти
// Опять критическая секция
SharedResource.Count++;
}
finally
{
if (lockTaken) // Если вошли-таки
{
Monitor.Exit(_syncObject); // То обязательно выходим, даже если посередине всё ебнулось
}
}
}
Так в чём же, блядь, разница, спросишь ты?
- Простота vs Контроль:
lock— это для ленивых и умных. Написал одну строчку — и спи спокойно.Monitor— когда нужно поковыряться в кишках. Сам всё контролируешь, сам и отвечаешь, если что-то пойдёт не так. - Фишки: Вот тут самое интересное. С
lockты просто ждёшь у двери, пока она откроется. А сMonitorможно постучаться и сказать: "Эй, я подожду пять секунд, а если не впустите — я пошёл нахуй!" ЭтоMonitor.TryEnterс таймаутом. Спасение от дедлоков, ёпта!- Ещё есть
Monitor.Wait()— типа "я пока выйду, разбудите, когда будет что поесть". - И
Monitor.Pulse()/PulseAll()— это как крикнуть тем, кто ждёт: "Эй, проснитесь, пельмени на столе!"
- Ещё есть
Короче, вывод такой:
Для 95% случаев — бери lock и не парься. Это надёжно и безопасно.
Но если вдруг твои потоки начинают друг друга ждать, мёртво виснуть или нужно организовать какую-то хитрожопую очередь — тогда уже лезь в Monitor и используй его методы по полной. Это как отвёртка против целого чемоданчика с инструментами. Выбирай по ситуации.