Reputation: 429
This code is used to demonstrate double-checked-locking anti-pattern:
@NotThreadSafe
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
Can I just avoid this problem by modify it to:
@NotThreadSafe
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null){
Resource r=new Resource();
resource = r;
}
}
}
return resource;
}
}
As far as I know,
Resource r=new Resource();
resource = r;
That compiler should provide happen-before relationship for that.
Upvotes: 1
Views: 203
Reputation: 65869
The compiler is allowed to optimise:
Resource r=new Resource();
resource = r;
to
resource=new Resource();
so your adjustment is ineffective.
Upvotes: 2
Reputation: 43748
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null){
Resource r=new Resource();
resource = r;
}
}
}
return resource;
}
The only thing that guarantees proper visibility between threads is creating synchronizes-with relationships via synchronization (via synchronized
, volatile
, ...).
If you don't have a synchronizes-with relationship, a thread is not required to see modifications from other threads.
In this case, a thread may create a Resource
and store a reference to it in resource
. Then a second thread may enter getInstance()
, and see resource != null
. This second thread is not guaranteed to see all the effects of resource
's constructions, since it isn't synchronized-with the first thread.
Upvotes: 2
Reputation: 30088
As far as I know, the only known implementation of the double-checked locking pattern that works (for JDK5 and above) makes use of the 'volatile' keyword. See Fixing Double-Checked Locking using Volatile
Upvotes: 4