Да — такой код может привести к взаимной блокировке (deadlock). Почему: если другой поток, скажем поток A, делает `lock(L1); sleep(); lock(L2);`, то возможна ситуация: - поток A держит L1L_1L1 и ждёт L2L_2L2; - поток B держит L2L_2L2 и ждёт L1L_1L1; в результате оба навсегда блокированы. Как избежать (кратко и по сути): - Глобальный порядок захвата: всегда захватывать мьютексы в одном порядке, например сначала L1L_1L1, затем L2L_2L2. - Не спать (не блокировать), удерживая мьютекс; выполнить sleep после release. - Попытка с откатом (try-lock): пытаться взять оба, при неудаче освобождать взятые и повторять с задержкой. Пример стратегии: попытаться `try_lock(L1)`, `try_lock(L2)` — если не удалось, `unlock` взятые и повторить через небольшой backoff. - Атомарное захватывание нескольких мьютексов: использовать `std::lock` / `std::scoped_lock` (или эквивалент), которые предотвращают взаимную блокировку. - Таймауты: использовать timed-локи и обрабатывать невозможность захвата. Выбор метода зависит от контекста; самый простой и надёжный — установить и соблюдать фиксированный порядок захвата ресурсов (L1L_1L1 прежде L2L_2L2).
Почему: если другой поток, скажем поток A, делает `lock(L1); sleep(); lock(L2);`, то возможна ситуация:
- поток A держит L1L_1L1 и ждёт L2L_2L2 ;
- поток B держит L2L_2L2 и ждёт L1L_1L1 ;
в результате оба навсегда блокированы.
Как избежать (кратко и по сути):
- Глобальный порядок захвата: всегда захватывать мьютексы в одном порядке, например сначала L1L_1L1 , затем L2L_2L2 .
- Не спать (не блокировать), удерживая мьютекс; выполнить sleep после release.
- Попытка с откатом (try-lock): пытаться взять оба, при неудаче освобождать взятые и повторять с задержкой.
Пример стратегии: попытаться `try_lock(L1)`, `try_lock(L2)` — если не удалось, `unlock` взятые и повторить через небольшой backoff.
- Атомарное захватывание нескольких мьютексов: использовать `std::lock` / `std::scoped_lock` (или эквивалент), которые предотвращают взаимную блокировку.
- Таймауты: использовать timed-локи и обрабатывать невозможность захвата.
Выбор метода зависит от контекста; самый простой и надёжный — установить и соблюдать фиксированный порядок захвата ресурсов (L1L_1L1 прежде L2L_2L2 ).