Назад к вопросам
Middle
80
questionbank
Какое минимальное количество мьютексов необходимо для возникновения дедлока?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Минимальное количество мьютексов для возникновения дедлока — два.
Дедлок может произойти при соблюдении четырех условий (условия Коффмана):
- Взаимное исключение (Mutual Exclusion): Ресурсы должны быть несовместно используемыми (non-shareable). В данном случае, мьютексы обеспечивают это.
- Удержание и ожидание (Hold and Wait): Процесс, уже владеющий одним мьютексом, пытается захватить еще один мьютекс, который занят другим процессом.
- Непередаваемость (No Preemption): Захваченный мьютекс не может быть принудительно отобран у процесса; он может быть освобожден только самим процессом.
- Циклическое ожидание (Circular Wait): Существует цепочка процессов, где каждый процесс ожидает мьютекс, захваченный следующим процессом в цепочке, и последний процесс в цепочке ожидает мьютекс, захваченный первым процессом.
Пример с двумя мьютексами:
#include <mutex>
#include <thread>
#include <iostream>
std::mutex mtx1;
std::mutex mtx2;
void thread1_func() {
mtx1.lock(); // Поток 1 захватывает mtx1
std::cout << "Thread 1 acquired mtx1" << std::endl;
// Искусственная задержка, чтобы увеличить вероятность дедлока
std::this_thread::sleep_for(std::chrono::milliseconds(100));
mtx2.lock(); // Поток 1 пытается захватить mtx2 (возможно, уже занят Потоком 2)
std::cout << "Thread 1 acquired mtx2" << std::endl;
mtx2.unlock();
mtx1.unlock();
}
void thread2_func() {
mtx2.lock(); // Поток 2 захватывает mtx2
std::cout << "Thread 2 acquired mtx2" << std::endl;
// Искусственная задержка, чтобы увеличить вероятность дедлока
std::this_thread::sleep_for(std::chrono::milliseconds(100));
mtx1.lock(); // Поток 2 пытается захватить mtx1 (возможно, уже занят Потоком 1)
std::cout << "Thread 2 acquired mtx1" << std::endl;
mtx1.unlock();
mtx2.unlock();
}
int main() {
std::thread t1(thread1_func);
std::thread t2(thread2_func);
t1.join();
t2.join();
return 0;
}
В этом примере, если Поток 1 захватит mtx1, а Поток 2 захватит mtx2 почти одновременно, то Поток 1 будет ждать mtx2 (который занят Потоком 2), а Поток 2 будет ждать mtx1 (который занят Потоком 1). Возникает циклическое ожидание между двумя потоками и двумя мьютексами.