---
title: Deadlock и состояние гонки
seo:
  title: Deadlock и состояние гонки — C++ Developer
  description: Тема «Deadlock и состояние гонки» для собеседования C++ Developer. Что такое deadlock? Как избежать состояния гонки?
---

[Все темы C++ Developer](/c-developer)

## <strong>Что такое</strong> <code>deadlock</code><strong>?</strong> [#q-14bee738d69b8173a7bdf257c3958dba]

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

#### Пример&#58;

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

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

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

#### Причины&#58;

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

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

#### Предотвращение&#58;

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

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

- Применение высокоуровневых средств синхронизации (например, <code>std&#58;&#58;lock</code> для атомарного захвата нескольких мьютексов).

#### Пример&#58;

```cpp
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();
```

:::note[Ссылки для изучения]

1. [Заметки о синхронизации. Deadlock](https://habr.com/ru/articles/119438/)
   :::

---

## <strong>Как избежать состояния гонки?</strong> [#q-14bee738d69b813b8124ca49e1f8629e]

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

{/* prettier-ignore */}
1. <strong>Использование мьютексов (</strong><code>std&#58;&#58;mutex</code><strong>)</strong>&#58;

    - Защищает критические секции кода, обеспечивая доступ к ним только одному потоку за раз.

    ```cpp
    std::mutex mtx;
    void threadFunc() {
        std::lock_guard<std::mutex> lock(mtx);
        // Доступ к общим данным
    }
    ```

1. <strong>Использование атомарных операций (</strong><code>std&#58;&#58;atomic</code><strong>)</strong>&#58;

    - Обеспечивает атомарные обращения к отдельному объекту. Несколько операций над ним или согласование нескольких переменных требуют отдельного анализа. Реализация не всегда lock-free.

    ```cpp
    std::atomic<int> counter(0);
    void increment() {
        counter++;
    }
    ```

1. <strong>Использование условных переменных (</strong><code>std&#58;&#58;condition&#95;variable</code><strong>)</strong>&#58;

    - Синхронизирует потоки, ожидая выполнения определённых условий.

    ```cpp
    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; });
        // Доступ к общим данным
    }
    ```

1. <strong>Соблюдение порядка захвата ресурсов</strong>&#58;

    - Захват ресурсов всегда в одном и том же порядке для всех потоков.

    ```cpp
    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);
        // Доступ к общим данным
    }
    ```

:::note[Ссылки для изучения]

1. [Небезопасная многопоточность](https://habr.com/ru/articles/764234/)
   :::
