When acquiring a lock on instance variable, does JVM "refresh" a state of whole instance or just the state of that particular variable?
Consider implementation of following class
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;
}
}
Two threads T1 and T2, statements are executed top to bottom
T1 -> setFlag()
T2 -> getFlag()
At this point, its obvious that T2 will most likely see the stale data as neither synchronization, nor volatile keyword was used.
However, if T2 subsequently sends messages
T2 -> refreshLock()
T2 -> getFlag()
does getFlag() method returns most up-to-date value? According to test that I've done it does.
If it's really true, could somebody please explain me why acquiring the lock on instance variable refreshes the entire owner's state and not just the state of that particular variable? I've already took a look into a JLS 17.4.4., but still can't figure it out.
Test
I used following code to test behavior described above
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();
}
}
Update #1
I've slightly edited SyncObject implementation and added visibility attribute as well as refreshVisibility method. If refreshLock method in test case is replaced by refreshVisibility, the behavior is the same and thread finished in about 1s.
refreshLock()aftersetFlag().concurrentpackage:An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor. And because the happens-before relation is transitive, all actions of a thread prior to unlocking happen-before all actions subsequent to any thread locking that monitor.That being said, if I callrefreshLock()on T1, subsequent lock on T2 would probably ensured consistency among threads.volatilevariable instead. Looks like it doesn't matter at all that T1 didn't write to that variable, T2 still saw most up-to-date state oncevolatilevariable had been read. Maybe because of transitive relation of thehappens-before?