В чем разница между Lock и Monitor в .NET?

Ответ

В .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); // Явное освобождение
        }
    }
}

Ключевые различия

  1. Удобство и безопасность: lock проще и безопаснее, так как компилятор сам генерирует корректный код освобождения в finally.
  2. Гибкость: 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); // То обязательно выходим, даже если посередине всё ебнулось
        }
    }
}

Так в чём же, блядь, разница, спросишь ты?

  1. Простота vs Контроль: lock — это для ленивых и умных. Написал одну строчку — и спи спокойно. Monitor — когда нужно поковыряться в кишках. Сам всё контролируешь, сам и отвечаешь, если что-то пойдёт не так.
  2. Фишки: Вот тут самое интересное. С lock ты просто ждёшь у двери, пока она откроется. А с Monitor можно постучаться и сказать: "Эй, я подожду пять секунд, а если не впустите — я пошёл нахуй!" Это Monitor.TryEnter с таймаутом. Спасение от дедлоков, ёпта!
    • Ещё есть Monitor.Wait() — типа "я пока выйду, разбудите, когда будет что поесть".
    • И Monitor.Pulse() / PulseAll() — это как крикнуть тем, кто ждёт: "Эй, проснитесь, пельмени на столе!"

Короче, вывод такой:
Для 95% случаев — бери lock и не парься. Это надёжно и безопасно.
Но если вдруг твои потоки начинают друг друга ждать, мёртво виснуть или нужно организовать какую-то хитрожопую очередь — тогда уже лезь в Monitor и используй его методы по полной. Это как отвёртка против целого чемоданчика с инструментами. Выбирай по ситуации.