При получении блокировки для переменной экземпляра JVM "обновляет" состояние целого экземпляра или только состояние этой конкретной переменной?
Рассмотрим реализацию следующего класса
public class SyncObject {
private boolean flag = false;
private final Object lock = new Object();
private volatile Object visibility = null;
public void setFlag() {
a = true;
}
public boolean getFlag() {
return flag;
}
public void refreshLock() {
synchronized(lock){
;
}
}
public void refreshVisibility() {
Object dummy = visibility;
}
}
Два потока T1 и T2, операторы выполняются сверху вниз
T1 -> setFlag()
T2 -> getFlag()
На данный момент очевидно, что T2, скорее всего, увидит устаревшие данные, поскольку не использовались ни синхронизация, ни ключевое слово volatile
.
Однако, если T2 впоследствии отправляет сообщения
T2 -> refreshLock()
T2 -> getFlag()
метод getFlag()
возвращает наиболее актуальное значение? Согласно тесту, который я сделал , он делает .
Если это действительно так, может кто-нибудь объяснить, пожалуйста , почему получение блокировки переменной экземпляра обновляет состояние всего владельца, а не только состояние этой конкретной переменной ? Я уже взглянул на JLS 17.4.4. , но до сих пор не могу понять.
Test
Я использовал следующий код для проверки поведения, описанного выше
public class Main {
public static void main(String[] args) {
final SyncObject sObject = new SyncObject();
Thread background = new Thread(() -> {
while(!sObject.getFlag()){
// if line below is uncommented, thread finishes in roughly 1s, otherwise it loops forever
//sObject.refreshLock();
}
});
background.start();
TimeUnit.SECONDS.sleep(1);
sObject.setFlag();
}
}
Обновление # 1
Я немного отредактировал реализацию SyncObject
и добавил атрибут visibility
, а также метод refreshVisibility
. Если метод refreshLock
в тестовом примере заменяется на refreshVisibility
, поведение остается таким же, и выполнение потока завершается примерно через 1 с.