Ответ
Нет, классический deadlock (взаимная блокировка) требует циклической зависимости как минимум между двумя потоками и двумя ресурсами. На одном мьютексе это невозможно.
Однако, можно вызвать самоблокировку (self-deadlock), если поток попытается повторно захватить нерекурсивный мьютекс, который он уже удерживает.
#include <mutex>
std::mutex mtx;
void problematic_function() {
mtx.lock();
// ... какой-то код ...
mtx.lock(); // Поток заблокируется здесь, ожидая самого себя -> deadlock
mtx.unlock();
mtx.unlock();
}
Решение:
- Использовать
std::recursive_mutex, который позволяет одному потоку захватывать его несколько раз. - Перепроектировать код, чтобы избежать повторного захвата. Часто это признак плохой структуры.
- Использовать
std::lock_guardилиstd::unique_lockсstd::defer_lockиstd::try_lockдля безопасных попыток захвата.
// Решение с recursive_mutex
std::recursive_mutex rec_mtx;
void safe_function() {
std::lock_guard<std::recursive_mutex> lock(rec_mtx);
// ... можно вызывать другую функцию, которая тоже захватывает этот мьютекс
}