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

Что такое DeadLock

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

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

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

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

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

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

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

Пример Deadlock в C++

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

#include <iostream>
#include <thread>
#include <mutex>
​
std::mutex mutex1;
std::mutex mutex2;
​
void Thread1() {
    // Поток 1 захватывает первый мьютекс
    std::lock_guard<std::mutex> lock1(mutex1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Имитируем работу
​
    // Поток 1 пытается захватить второй мьютекс
    std::lock_guard<std::mutex> lock2(mutex2);
    std::cout << "Thread 1 has locked both mutexes" << std::endl;
}
​
void Thread2() {
    // Поток 2 захватывает второй мьютекс
    std::lock_guard<std::mutex> lock2(mutex2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Имитируем работу
​
    // Поток 2 пытается захватить первый мьютекс
    std::lock_guard<std::mutex> lock1(mutex1);
    std::cout << "Thread 2 has locked both mutexes" << std::endl;
}
​
int main() {
    std::thread t1(Thread1);
    std::thread t2(Thread2);
​
    t1.join();
    t2.join();
​
    return 0;
}

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

  • std::mutex mutex1; и std::mutex mutex2;: Объявление двух мьютексов, которые будут использоваться для синхронизации потоков.
  • void Thread1() и void Thread2(): Две функции, которые будут выполняться в отдельных потоках. Каждая из них захватывает мьютексы в разном порядке.
  • std::lock_guard<std::mutex> lock1(mutex1);: Поток 1 захватывает mutex1. std::lock_guard автоматически освобождает мьютекс при выходе из области видимости.
  • std::lock_guard<std::mutex> lock2(mutex2);: Поток 2 захватывает mutex2.
  • std::this_thread::sleep_for(std::chrono::milliseconds(100));: Задержка для имитации работы и увеличения вероятности возникновения deadlock.
  • std::lock_guard<std::mutex> lock2(mutex2); и std::lock_guard<std::mutex> lock1(mutex1);: Потоки пытаются захватить второй мьютекс, что может привести к deadlock, если оба потока уже удерживают первый мьютекс.

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

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

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

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

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

Твои заметки