Ответ
Deadlock (взаимная блокировка) — это ситуация в многопоточном программировании, когда два или более потока заблокированы, каждый ожидает освобождения ресурса, удерживаемого другим, создавая циклическую зависимость.
Классический пример на C++ с std::mutex:
#include <thread>
#include <mutex>
#include <chrono>
std::mutex mutex1, mutex2;
void thread1_work() {
std::lock_guard<std::mutex> lock1(mutex1); // Захватываем mutex1
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Имитация работы
std::lock_guard<std::mutex> lock2(mutex2); // Блокировка: ждём mutex2, который у thread2
// Критическая секция 1&2
}
void thread2_work() {
std::lock_guard<std::mutex> lock2(mutex2); // Захватываем mutex2
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::lock_guard<std::mutex> lock1(mutex1); // Блокировка: ждём mutex1, который у thread1
// Критическая секция 2&1
}
// Запуск t1 и t2 приведёт к deadlock.
Способы предотвращения, которые я применяю:
- Упорядоченная блокировка: Всегда захватывать мьютексы в одном и том же глобальном порядке (напр., сначала
mutex1, потомmutex2). - Использование
std::lock: Стандартная функция, которая безопасно захватывает несколько мьютексов, избегая deadlock.std::lock(mutex1, mutex2); // Атомарно захватывает оба std::lock_guard<std::mutex> lk1(mutex1, std::adopt_lock); std::lock_guard<std::mutex> lk2(mutex2, std::adopt_lock); - Избегание вложенных блокировок: Перепроектирование кода, чтобы уменьшить необходимость удерживать несколько мьютексов.
- Использование
std::scoped_lock(C++17): Более современная и безопасная заменаstd::lock_guardдля нескольких мьютексов.std::scoped_lock lock(mutex1, mutex2); // Deadlock-free захват
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶