Если вы изменяете все synchronized
блоков (и методы), и все другие блокирующие структуры, я думаю, вы должны быть хорошо - в худшем случае, ваше приложение вырождается к наличию последовательного выполнения. Но если вы только измените некоторые из них, вы можете зайти в тупик. Рассмотрим ситуацию, когда два потока, каждый приобретающие несколько блокировок:
Thread 1:
synchronized A
synchronized B
Thread 2:
synchronized B
synchronized C
Там нет никакого риска тупика, но если вы замените A
и C
(но не B
) с новым, общим замком, то вы будете иметь :
Thread 1:
synchronized L
synchronized B
Thread 2:
synchronized B
synchronized L
... классический тупик.
Рассмотрим другого сценария, где замки не обеспечивают тупиковые себя, но вместо этого ТУПИКА класс блокирующего как CountDownLatch:
Thread 1:
synchronized A
latch L.countDown()
Thread 2:
synchronized B
latch L.await()
В этом случае изменение оба synchronized
блоков, чтобы зафиксировать на общий замок выиграл 't вызывают взаимоблокировку между ними, но вызовут тупик, если поток 2 сначала получит блокировку: он будет ожидать счетчик задержек, который никогда не появится, потому что поток 1 заблокирован в точке входа . Этот пример применим и к другим структурам блокировки: семафорам, очередям блокировки и т. Д.
Можете ли вы опубликовать фрагмент кода? –
Нет, это как 3000+ линий. : -D Это не мой код, заметьте ... –
Из того, что я понимаю, если вам нужно атомарность для всех методов, вам нужно иметь один замок, если вы хотите справедливости, чтобы каждый поток обслуживался процессор в том порядке, в котором они ищут ресурс, вы можете взглянуть на java.util.concurrent.Lock (что гарантирует справедливость, но это связано с накладными расходами). Прочтите http://www.ibm.com/developerworks/java/library/j-jtp09238/index.html и http://www.ibm.com/developerworks/java/library/j-jtp10264/ для лучшего понимания блокировки и происходит - перед заказом в java. –