Sobes.tech
Назад к вопросам
Junior — Middle
59

Что именно передается или используется в механизме блокировки (lock) в многопоточном программировании?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

В lock передается не «сам поток», а объект, который используется как монитор синхронизации. Важен именно общий и стабильный объект, одинаковый для всех потоков, которые должны взаимно исключать доступ. В C# lock гарантирует, что в критическую секцию одновременно войдет только один поток.

Определение:

lock в C# — это синтаксический сахар над Monitor.Enter / Monitor.Exit. В качестве аргумента используется ссылка на объект, по которому выполняется синхронизация. Пока один поток держит этот объект под блокировкой, другие потоки, пытающиеся захватить тот же объект, будут ждать.

Обычно для этого используют отдельный приватный объект, а не this, не строковые литералы и не публично доступные объекты. Это снижает риск внешней блокировки и взаимных зависаний.

Пример использования:

public class Counter
{
    private readonly object _sync = new object();
    private int _value;

    public void Increment()
    {
        lock (_sync)
        {
            _value++;
        }
    }

    public int Value => _value;
}

Здесь _sync — это объект-монитор. Если несколько потоков одновременно вызовут Increment(), они будут заходить в блок lock по очереди.

Пояснение кода:

Код нужен, потому что механизм lock лучше всего объясняется на простом примере.

  1. Создается приватный объект _sync, который никто снаружи не использует.
  2. Метод Increment() входит в критическую секцию через lock (_sync).
  3. Первый поток захватывает монитор объекта _sync и выполняет _value++.
  4. Остальные потоки, которые пришли в lock (_sync), блокируются до освобождения монитора.
  5. После выхода из блока lock монитор освобождается автоматически.

Так обеспечивается атомарность операции увеличения счетчика: без блокировки два потока могли бы одновременно прочитать одно и то же значение и потерять одно из увеличений.

Ключевые моменты:

  • В lock передается объект, а не поток и не число.
  • Один и тот же объект должен использоваться всеми потоками, которым нужна общая синхронизация.
  • Для блокировки лучше брать private readonly object.
  • Не стоит блокироваться на this, typeof(...) и строковых литералах — это может привести к внешним конфликтам.
  • lock защищает только код внутри критической секции, а не весь объект целиком.
  • В C# lock автоматически освобождает монитор при выходе из блока, даже при исключении.