Перейти к содержимому
На этой странице

Deadlock и состояние гонки

Все темы C++ Developer

Что такое deadlock?

Deadlock (взаимная блокировка) — это состояние, при котором два или более потоков навсегда заблокированы, ожидая ресурсы, захваченные друг другом. Это приводит к остановке выполнения программы.

Пример:

  1. Поток A захватывает ресурс 1 и ждёт ресурс 2.

  2. Поток B захватывает ресурс 2 и ждёт ресурс 1.

  3. Оба потока остаются заблокированными, ожидая освобождения ресурсов.

Причины:

  • Неправильный порядок захвата ресурсов.

  • Нарушение правил синхронизации.

Предотвращение:

  • Использование таймаутов при захвате мьютексов.

  • Соблюдение единого порядка захвата ресурсов.

  • Применение высокоуровневых средств синхронизации (например, std::lock для атомарного захвата нескольких мьютексов).

Пример:

std::mutex mtx1, mtx2;

void threadA() {
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock2(mtx2);
}

void threadB() {
    std::lock_guard<std::mutex> lock2(mtx2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock1(mtx1);
}

std::thread t1(threadA);
std::thread t2(threadB);
t1.join();
t2.join();

Как избежать состояния гонки?

Чтобы избежать состояния гонки (race condition) в многопоточном программировании, необходимо правильно синхронизировать доступ к общим ресурсам. Вот несколько методов:

  1. Использование мьютексов (std::mutex):

    • Защищает критические секции кода, обеспечивая доступ к ним только одному потоку за раз.
    std::mutex mtx;
    void threadFunc() {
        std::lock_guard<std::mutex> lock(mtx);
        // Доступ к общим данным
    }
  2. Использование атомарных операций (std::atomic):

    • Обеспечивает атомарные обращения к отдельному объекту. Несколько операций над ним или согласование нескольких переменных требуют отдельного анализа. Реализация не всегда lock-free.
    std::atomic<int> counter(0);
    void increment() {
        counter++;
    }
  3. Использование условных переменных (std::condition_variable):

    • Синхронизирует потоки, ожидая выполнения определённых условий.
    std::mutex mtx;
    std::condition_variable cv;
    bool ready = false;
    void producer() {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
        cv.notify_one();
    }
    void consumer() {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{ return ready; });
        // Доступ к общим данным
    }
  4. Соблюдение порядка захвата ресурсов:

    • Захват ресурсов всегда в одном и том же порядке для всех потоков.
    std::mutex mtx1, mtx2;
    void threadFunc() {
        std::lock(mtx1, mtx2);
        std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
        std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
        // Доступ к общим данным
    }

Собеседования: C++

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: C++-разработчик, Разработчик системного ПО. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.