Этот вопрос мне задали года полтора назад на первом телефонном собеседовании в Майкрософт. Я ответил что-то невнятное типа «ну концентрировать весь concurrency-related код в как можно меньшем числе классов, чтобы удобнее было разбираться в проблеме». Это собеседование я не прошёл.
Java Concurrency in Practice для решения проблемы дедлоков предлагает, по крайней мере в главе про дедлоки, следующее решение:
If you must acquire multiple locks, lock ordering must be a part of your design: try to minimize the number of potential locking interactions, and follow and document a lock ordering protocol for locks that may be acquired together.
Однако более полный ответ на этот вопрос я увидел, как ни странно, в Чистом коде Боба Мартина, в той главе, которая там вроде как ни к месту. Там приводятся следующие обязательные условия возникновения дедлока:
- Mutual Exclusion
- Lock and Wait
- No Preemption
- Circular Wait
И предлагаются способы исключить каждое условие:
Mutual Exclusion:
- Использовать ресурсы, не требующие блокировки
- Увеличение количества ресурсов, чтобы у каждого потока был свой экземпляр
- Проверка, что ресурс свободен перед тем, как захватить его
От Lock and Wait избавиться можно так: проверяем ресурс перед захватом; если он занят, то освобождаем все захваченные ресурсы. Этот подход может привести к новым проблемам: Livelock и Starvation.
No Preemption: разрешаем потокам запрашивать ресурсы друг у друга. Я никогда в жизни такого не видел и не представляю, как это хорошо реализовать. Пишут, что это непросто.
Circular Wait: Вводим порядок, в котором ресурсы могут быть захвачены. Это невозможно, если до захвата одного ресурса мы не узнаем, какой ресурс понадобится следующим.
* * *
Особые юмористы могут отметить при ответе на вопрос, что переход на один лок или один поток также решает проблему.
Говноблогеры замучали засирать интернет своими hello word на любую тематику. Автор прочёл о принципах, известных больше 30 лет в книжке, не имеющей отношение к этим принципам! Какое достижение! Это повод для записи в блоге! Между прочим эти условия известны очень давно и описываются в любой книжке по операционным системам или многопоточному программированию. Это повод каждому говноблогеру написать об этом с воём говноблоге? В чём смысл просто пересказывать книги? Напиши код на 10 строк, чтобы не приходилось лазить в те самые книжки. Это всё не очевидно? Таненбаум, Хоар, Дейкстра – не, не слышл? Только писать на PHP слышал?