Reputation: 1072
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.
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();
}
}
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.
Upvotes: 1
Views: 268
Reputation: 2837
You should have a look at the following point, that is, happen-before relationship, https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5 .
You can be sure that write operations performed by thread A are visible to thread B, if the happen before relationship holds. And that is the case when you have the threads locking the monitor in turn, or the first writing and then the other reading from a volatile variable. (plus there are other cases listed in the doc).
Also, as explained in the guide visibility is not limited to a single variable, but to every variable which changed before the "barrier".
Upvotes: 1