Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про JavaScript: Lock, mutex, thread synchronization, race condition, concurrency

Что такое Lock и как он используется?

Вопрос проверяет понимание механизма блокировок (Lock) для синхронизации потоков и предотвращения состояния гонки при работе с общими ресурсами.

Короткий ответ

Lock (блокировка) — это примитив синхронизации, который позволяет только одному потоку одновременно выполнять критическую секцию кода. Он используется для защиты общих данных от одновременного изменения несколькими потоками, что предотвращает состояние гонки. Например, в Python можно использовать threading.Lock(). Поток захватывает блокировку методом acquire(), выполняет операции, а затем освобождает её release(). Если блокировка уже захвачена другим потоком, текущий поток будет ждать её освобождения.

Длинный ответ

Lock (часто называемый мьютексом) — это базовый механизм синхронизации в многопоточном программировании. Его основная цель — обеспечить эксклюзивный доступ к общему ресурсу (например, переменной, файлу, структуре данных) для одного потока в определённый момент времени. Это предотвращает состояние гонки (race condition), когда несколько потоков одновременно читают и изменяют данные, приводя к непредсказуемым и ошибочным результатам.

Как работает Lock

Lock имеет два основных состояния: "заблокирован" (locked) и "разблокирован" (unlocked). Когда поток хочет войти в критическую секцию (участок кода, работающий с общим ресурсом), он пытается захватить блокировку. Если блокировка свободна, поток захватывает её и продолжает выполнение. Если же блокировка уже захвачена другим потоком, текущий поток блокируется (переходит в состояние ожидания) до тех пор, пока блокировка не будет освобождена.

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

Рассмотрим классический пример с увеличением счётчика из нескольких потоков без блокировки и с её использованием.

import threading

# Общий ресурс
counter = 0

# Функция без защиты
def increment_without_lock():
    global counter
    for _ in range(100000):
        counter += 1  # Это не атомарная операция!

# Функция с защитой Lock
lock = threading.Lock()
def increment_with_lock():
    global counter
    for _ in range(100000):
        lock.acquire()  # Захватываем блокировку
        try:
            counter += 1
        finally:
            lock.release()  # Всегда освобождаем

# Создаём потоки
threads = []
for _ in range(10):
    t = threading.Thread(target=increment_with_lock)
    threads.append(t)
    t.start()

# Ждём завершения всех потоков
for t in threads:
    t.join()

print(f"Final counter: {counter}")  # Будет 1000000 только с Lock

Где применяются блокировки

  • Многопоточные приложения: Защита структур данных (списков, словарей) в веб-серверах, GUI-приложениях.
  • Базы данных: Транзакции часто используют блокировки для обеспечения изоляции (например, SELECT FOR UPDATE).
  • Операционные системы: Синхронизация доступа к системным ресурсам (файлам, сокетам).
  • Параллельные алгоритмы: Когда несколько процессов или потоков должны координировать доступ к общему состоянию.

Важные аспекты и подводные камни

  • Взаимная блокировка (deadlock): Может возникнуть, если два потока захватывают несколько блокировок в разном порядке. Решение — всегда захватывать блокировки в одинаковом порядке.
  • Голодание (starvation): Если один поток долго удерживает блокировку, другие могут долго ждать.
  • Производительность: Излишнее использование блокировок может свести на нет преимущества многопоточности.
  • Рекурсивные блокировки (RLock): Позволяют одному потоку захватывать одну и ту же блокировку несколько раз.

Вывод: Lock — фундаментальный инструмент для безопасной работы с общими ресурсами в многопоточной среде. Его стоит применять всегда, когда несколько потоков могут одновременно изменять одни и те же данные. Однако важно использовать блокировки аккуратно, чтобы избежать взаимных блокировок и не снизить производительность.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • JavaScript

    JavaScript

  • Node.js

    Node.js

Ключевые слова

#Lock

#mutex

#thread synchronization

#race condition

#concurrency

Подпишись на Java Developer в телеграм