Добавление другого ответа, потому что я не согласен с решениями, предложенными cHao ранее - анализ в порядке.
Во-первых, почему я не согласен с двумя предлагаемыми решениями:
Уменьшение разногласий
Разногласия не приводят к тупикам.Это просто вызывает плохую производительность.Тупик означает нет производительность вообще.Поэтому уменьшение конкуренции не решает взаимоблокировки.
Тайм-аут на мьютекс.
Мьютекс защищает ресурс, а поток блокирует мьютекс, потому что ему нужен ресурс.По истечении времени ожидания вы не сможете получить ресурс, и ваш поток завершится ошибкой.Это решает проблему тупика?Только если сбойный поток освобождает другой ресурс, который блокировал другие потоки.
Но в этом случае есть гораздо лучшее решение.Мьютексы должны иметь частичное упорядочение.Если есть хотя бы один поток, который может одновременно мьютекс A и B, вы должны решить, будет ли A или B получен первым, а затем придерживаться этого .Это должен быть транзитивный порядок: если вы блокируете A перед B, а B перед C, то, очевидно, вы должны заблокировать A до C.
Это идеальное решение для взаимоблокировок.Посмотрите на пример тайм-аута: он работает только в том случае, если поток, ожидающий в ожидании на A, освобождает свою блокировку на B, чтобы освободить другой поток, ожидающий на B. В самом простом случае этот другой поток сам непосредственно блокировал AТаким образом, мьютексы A и B не упорядочены должным образом.Сначала вы должны были последовательно заблокировать A или B.
Случай тайм-аута также может быть результатом проблемы циклического порядка;один поток блокирует A, затем B, другой B, затем C, и третий C, затем A, при этом возникает взаимоблокировка, когда каждому потоку принадлежит одна блокировка.Решение снова то же самое;упорядочить блокировки.
В качестве альтернативы, порядки блокировки мьютекса могут быть описаны ориентированным графом.Если поток блокирует A до B, есть дуга от A до B. Появляются тупики, если ориентированный граф циклический, и тогда дуги этого цикла являются взаимоблокированными потоками.
Эта теория может быть немного сложной, но есть несколько простых идей, которые можно найти.Например, из теории графов мы знаем, что деревья являются ациклическими графами.Следовательно, ни «листовые взаимные блокировки» (те, которые всегда заблокированы last ), ни «корневые взаимные блокировки» (те, которые всегда заблокированы first ) не могут вызвать взаимные блокировки.Листовые мьютексы исключаются, потому что ни один поток никогда не блокирует их удержание, а корневые мьютексы исключаются, поскольку содержащий их поток сможет своевременно заблокировать все последующие мьютексы.