There are related questions but they as the focus in those is more on volatile and not much on the usage of local variable, hence I am posting a new question, Please see the question below.
Sonar Source rule has a code according to which below code is correct and solves the issues with DCL
class ResourceFactory {
private volatile Resource resource;
public Resource getResource() {
Resource localResource = resource;
if (localResource == null) {
synchronized (this) {
localResource = resource;
if (localResource == null) {
resource = localResource = new Resource();
}
}
}
return localResource;
}
static class Resource {
}
}
I understand that we have alternate options (some better than complicated DCL) like an
- enum or
- static inner class holder or
- a static final reference initialized during its declaration itself.
- declare the entire method as synchronized.
I wish to understand the usage of volatile along with local variable to resolve the issues for DCL.
Also I understand volatile (for Java 1.5 and later versions) guarantees the 'happens-before' feature which prevents the in-complete object being returned for reading.
Question 1 I want to understand as what is the need of volatile if a local variable has already been used. Below code has non volatile variable resource
but inside the getResource()
a local variable is used to read the resource
. Are there still issues in the code ? (Please see comments in below code below)
class ResourceFactory {
private Resource resource; // non volatile
public Resource getResource() {
Resource localResource = resource; // only 1 read without lock
if (localResource == null) {
synchronized (this) {
localResource = resource; // read inside the synchronized block
if (localResource == null) {
localResource = new Resource(); // constructor is initialized.
resource = localResource; // ****code reaches here only when constructor has been complete. Here is there a chance of resource being referring to incomplete object ?****
}
}
}
return localResource;
}
static class Resource {
}
}
The only advantage I see is with volatile is suppose the object was created then the first read itself would have guaranteed a memory read instead of read from thread cache preventing unnecessary acquisition of lock.
Question 2 Instead of using local variable if simple volatile was used then was the code without issues ?