Java: вложенные блоки синхронизации
Я видел это в одном из выпусков информационных выпусков Heinz Kabutz Java Specialist и, хотя все статьи (и действительно все) статей доктора Кабуца хорошо объяснены и детализированы, он, казалось, замалчивал то, что делает этот код, или что еще важнее:
public class SomeObject {
private Object lock1;
private Object lock2;
public void doSomething() {
synchronized(lock1) {
synchronized(lock2) {
// ...
}
}
}
}
Каковы последствия вложенности блоков synchronized
? Как это влияет на различные потоки, пытающиеся выполнить doSomething()
?
Ответы
Ответ 1
Есть две возможные проблемы, которые нужно было бы соблюдать
Ответ 2
Само по себе этот фрагмент кода не вызовет никаких проблем.
Но проблема может возникнуть в виде тупика, если есть что-то вроде этого кода; где у нас есть два метода с синхронизированными блоками таким образом, что объекты блокируются в противоположных порядках -
public void doSomething() {
synchronized(lock1) {
synchronized(lock2) {
// ...
}
}
}
public void doOtherthing() {
synchronized(lock2) {
synchronized(lock1) {
// ...
}
}
}
теперь, если более чем один поток пытается получить доступ к этим методам, тогда может быть тупик из-за вложенных синхронизированных блоков.
Ответ 3
В соответствии с Учебник по блокировке вложенных мониторов
Во вложенной блокировке монитора в Thread 1 выполняется блокировка A и ждет для сигнала из нити 2. Резьбе 2 требуется блокировка A для отправки сигнал к потоку 1. В тупике два потока ждут друг от друга, чтобы освободить блокировки.
Тупик может быть аналогичен двум лицам, заключенным в тюрьму в двух комнатах, они хотят переключиться на другую комнату, но у обоих из них есть только их копия. В то время как вложенная блокировка монитора точно так же, как босс устроен, чтобы спать в комнате, и предположим, что он проснется только тогда, когда кто-то войдет в комнату. И секретарь отвечает за пробуждение своего босса. Но босс все еще держал ключ от комнаты, когда спал, поэтому секретарь не смог прийти, чтобы разбудить его.