Два мьютекса захватываются в разном порядке: как убрать взаимную блокировку
Сервис изредка полностью перестаёт отвечать. В стеках потоков видно ожидание на мьютексах:
void move_a_to_b() {
std::lock_guard<std::mutex> l1(m_a);
std::lock_guard<std::mutex> l2(m_b);
// ...
}
void move_b_to_a() {
std::lock_guard<std::mutex> l1(m_b);
std::lock_guard<std::mutex> l2(m_a);
// ...
}
Выберите способы, которые действительно устраняют взаимную блокировку.
правильных вариантов может быть несколько
- Ввести единый порядок захвата и соблюдать его во всех функциях, работающих с этой парой мьютексов
- Захватывать оба мьютекса одной операцией, специально предназначенной для нескольких блокировок сразу
- Заменить обычный мьютекс на рекурсивный, чтобы повторный захват не приводил к остановке потока
- Добавить небольшую задержку перед захватом второго мьютекса, чтобы потоки расходились по времени
- Повысить приоритет потока, который чаще выполняет move_a_to_b, чтобы он успевал захватить оба мьютекса
