I am reading concurrency in practice and have some misunderstanding.
quote:
the real problem with DCL is the assumption that the worst thing that can happen when reading the shared object reference without synchronization is to erroneously see a stale value (in this case, null); in that cse the DCL idiom compensates for this risk by trying again with the lock held. But the worst case is actually considerably wrong - it is possible to see a current value of the reference but stale values for the object's states, meaning that the object could be seen to be in an invalid or incorrect state.
after Brian Goetz writes that DCL will work in current memory model using volatile:
public class DoubleCheckLociing{
private static volatile Resource resource;
public static Resource getInstance(){
if(resource == null){
synchronized(DoubleCheckLociing.class){
if(resource == null){
resource = new Resource();
}
}
}
return resource;
}
}
I am not sure if understand the phrase about state correct.
Lets imagine that Resource
class looks like this:
class Resource{
private Date date = new Date();//mutable thread unsafe class
private int k = 10;
public Date getDate(){
return date;
}
public int getK(){
return k;
}
}
Does I have guaranties that getInstance
always return correct
resource which always return correct k
(10) and date
?
With the volatile
in place you do have those guarantees. Without the volatile
you do not.
When one thread writes the volatile variable resource
, the operation includes a 'memory barrier' that ensures that everything it wrote before that, like the initialization of the instance fields, is written out to system memory first.
When another thread reads resource
, it includes a memory barrier that ensures that no reads performed after that will see values that were cached from system memory before that read.
These two memory barriers ensure that if a thread sees an initialized resource
variable, then it will also see properly initialized fields in that object.