Заблокированный Lock
может быть собран мусором, когда он больше недоступен.(Определение «достижимости» в JLS: «Достижимый объект - это любой объект, к которому можно получить доступ в любом потенциальном продолжающемся вычислении из любого живого потока.» - JLS 12.16.1)
Однако заблокированный Lock
, который ожидает некоторый поток на , должен выполнять один из методов экземпляра Lock / tryLock.Для этого поток должен иметь ссылку на блокировку;то есть тот, к которому в настоящее время обращается метод блокировки.Следовательно, заблокированная блокировка, которую пытается получить какой-то поток, достижима и не может быть собрана сборщиком мусора.
Другими словами, создает ли lock.lock () какие-либо сильные ссылки обратно на блокировку?
Нет.В вашем примере сильная ссылка существует в виде переменной lock
.Но предположим, что мы настроили ваш пример, чтобы избавиться от lock
;Например,
public void do_lock(WeakReference<ReentrantLock> r)
r.get().lock();
}
Когда вы вызываете get()
, он вернет ссылку на объект ReentrantLock
, который будет храниться во временной переменной или регистре, что делает его полностью достижимым.Он будет оставаться доступным до тех пор, пока выполняется вызов lock()
.Когда возвращается вызов lock()
, объект ReentrantLock
может стать слабо доступным (снова).
Откуда вы знаете?
Откуда мне знать?Сочетание:
- знание определения достижимости Спецификации языка Java и других вещей,
- опыта реализации JVM,
- старой доброй старомодной логики и...
- Я подтвердил это, прочитав исходный код OpenJDK (хотя это не доказывает ничего о JVM в целом.)
Там нетнеобходимо реализовать Lock
, используя глобальные очереди, и, следовательно, нет причин иметь скрытую ссылку на объект Lock
, который бы препятствовал тому, чтобы он стал недоступным.Кроме того, Lock
, который нельзя было собрать мусором, когда он был заблокирован, будет утечкой памяти и серьезным недостатком реализации, и я не могу представить Даг Ли и др., Совершающих эту ошибку!