Возможно ли восстановление тупика в программировании MultiThread? - PullRequest
3 голосов
/ 03 октября 2010

Процесс имеет около 10 потоков, и все 10 потоков вошли в состояние DEADLOCK (предположим, что все ожидают переменную Mutex).

Как вы можете освободить процесс (потоки) из состояния DEADLOCK?,Есть ли способ убить поток с более низким приоритетом? (В случае нескольких процессов мы можем убить процесс с более низким приоритетом, когда все процессы находятся в состоянии взаимоблокировки).

Можем ли мы присоединить этот заблокированный процесс к отладчику и назначить правильное значение дляПеременная Mutex (предположим, что все потоки ожидают MUT-переменной MUT, но это значение равно 0, и мы можем присвоить значение MUT 1 через отладчик).

Ответы [ 2 ]

5 голосов
/ 03 октября 2010

Если все потоки в приложении ожидают друг друга, и ни один из них не настроен на тайм-аут, вы скорее всего облажались.Возможно, вы сможете запустить приложение в отладчике или что-то в этом роде, но блокировки, как правило, приобретаются по определенной причине - и ручное принудительное использование мьютекса потоком, который не получил его законным путем, может вызвать некоторые большие проблемы (потокранее принадлежавший ему, он все еще попытается выпустить его, результаты которого могут быть непредсказуемыми, если мьютекс будет неожиданно вырван. Может вызвать неожиданное исключение, может вызвать разблокировку мьютекса, пока он еще используется.) В любом случае, он побеждаетцели мьютексов, так что вы просто прикрываете гораздо большую проблему.

Есть два общих решения:

  • Вместо того, чтобы потоки ждали вечно, установитетайм-аут.Это немного сложнее сделать в таких языках, как Java, которые встраивают мьютексы в язык с помощью блоков synchronized или lock, но это почти всегда возможно.Если вы перестанете ждать ожидания блокировки, отпустите все имеющиеся у вас блокировки / мьютексы и попробуйте позже.

  • Лучше, но потенциально гораздо сложнее, выяснить, почему все борются заресурс и удали это утверждение.Если вы должны заблокировать, заблокируйте последовательно.Но если на одном мьютексе блокируется 10 потоков, это может быть подсказкой либо о том, что ваши операции плохо разбиты на части (т. Е. Что ваши потоки делают слишком много или слишком мало сразу перед попыткой получить блокировку), либо в том, что нет необходимостиблокировка продолжается.Не блокируйте, если не нужно.Некоторая синхронизация может быть устранена путем использования коллекций и алгоритмов, специально разработанных так, чтобы они были «свободными от блокировки» и в то же время обеспечивали безопасность потоков.

4 голосов
/ 04 октября 2010

Добавление другого ответа, потому что я не согласен с решениями, предложенными 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 ) не могут вызвать взаимные блокировки.Листовые мьютексы исключаются, потому что ни один поток никогда не блокирует их удержание, а корневые мьютексы исключаются, поскольку содержащий их поток сможет своевременно заблокировать все последующие мьютексы.

...