Suppose we are instantiating a singleton using double-checked locking:
public static Instance getInstance() {
if (this.instance == null) {
synchronized(Instance.class) {
if (this.instance == null) {
this.instance = new Instance();
}
}
}
return this.instance;
}
The question is in the semantics of the program if instance
variable would be volatile and double-checked locking would be removed.
private volatile static Instance instance;
public static Instance getInstance() {
if (this.instance == null) {
this.instance = new Instance();
}
return this.instance;
}
Will the class get instantiated only once? Or, put another way, can volatile reads clash in such a way that two threads will see null
value of the reference and double instantiation will be performed?
I am aware of the happens-before relationship between volatile write and volatile read, and that volatile forbids caching (so all reads and writes will be executed in main memory, not in processor's cache), but it isn't clear in the case of concurrent volatile reads.
P.S.: the question is not in applying of the Singleton pattern (it was just an example where the problem is clear), it is just about if double-checked locking can be replaced with volatile read - volatile write without program semantics change, nothing more than that.