← Назад ко всем вопросам

Приведи пример DeadLock

1️⃣ Как кратко ответить

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

2️⃣ Подробное объяснение темы

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

Условия возникновения Deadlock

Для возникновения deadlock должны быть выполнены следующие условия:

  1. Взаимное исключение: Ресурсы не могут быть разделены, и каждый ресурс может быть занят только одним потоком в данный момент времени.
  2. Удержание и ожидание: Поток, который уже удерживает один ресурс, может запросить дополнительные ресурсы и ждать их освобождения.
  3. Отсутствие принудительного освобождения: Ресурсы не могут быть принудительно отобраны у потока, они должны быть освобождены только самим потоком.
  4. Циклическое ожидание: Существует замкнутый цикл потоков, где каждый поток ожидает ресурс, удерживаемый следующим в цикле потоком.

Пример Deadlock в C++

Рассмотрим пример, где два потока пытаются захватить два мьютекса в разном порядке, что приводит к deadlock.

#include <iostream>
#include <thread>
#include <mutex>
​
// Два мьютекса, которые будут использоваться потоками
std::mutex mutex1;
std::mutex mutex2;
​
// Функция, выполняемая первым потоком
void threadFunction1() {
    // Захватываем первый мьютекс
    std::lock_guard<std::mutex> lock1(mutex1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Имитируем работу
​
    // Пытаемся захватить второй мьютекс
    std::lock_guard<std::mutex> lock2(mutex2);
    std::cout << "Thread 1 has locked both mutexes" << std::endl;
}
​
// Функция, выполняемая вторым потоком
void threadFunction2() {
    // Захватываем второй мьютекс
    std::lock_guard<std::mutex> lock1(mutex2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Имитируем работу
​
    // Пытаемся захватить первый мьютекс
    std::lock_guard<std::mutex> lock2(mutex1);
    std::cout << "Thread 2 has locked both mutexes" << std::endl;
}
​
int main() {
    // Создаем два потока, которые выполняют функции threadFunction1 и threadFunction2
    std::thread t1(threadFunction1);
    std::thread t2(threadFunction2);
​
    // Ожидаем завершения потоков
    t1.join();
    t2.join();
​
    return 0;
}

Объяснение кода

  • std::mutex mutex1; std::mutex mutex2;: Объявление двух мьютексов, которые будут использоваться для синхронизации потоков.

  • void threadFunction1(): Функция, выполняемая первым потоком. Она сначала захватывает mutex1, затем пытается захватить mutex2.

  • void threadFunction2(): Функция, выполняемая вторым потоком. Она сначала захватывает mutex2, затем пытается захватить mutex1.

  • std::lock_guardstd::mutex lock1(mutex1);: Захват мьютекса mutex1 с помощью lock_guard, который автоматически освободит мьютекс при выходе из области видимости.

  • std::this_thread::sleep_for(std::chrono::milliseconds(100));: Имитирует задержку, чтобы увеличить вероятность возникновения deadlock.

  • std::thread t1(threadFunction1); std::thread t2(threadFunction2);: Создание двух потоков, которые выполняют функции threadFunction1 и threadFunction2.

  • t1.join(); t2.join();: Ожидание завершения выполнения потоков.

Как избежать Deadlock

  1. Упорядочивание захвата ресурсов: Всегда захватывайте ресурсы в одном и том же порядке во всех потоках.
  2. Использование std::lock: Используйте std::lock для захвата нескольких мьютексов одновременно, чтобы избежать deadlock.
  3. Тайм-ауты: Используйте тайм-ауты при ожидании захвата мьютексов, чтобы избежать бесконечного ожидания.
  4. Избегание удержания и ожидания: Освобождайте все удерживаемые ресурсы перед захватом новых.

Тема: Многопоточность / Синхронизация
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки