As I understand, this is a correct implementation of the double-checked locking pattern in Java (since Java 5):
class Foo {
private volatile Bar _barInstance;
public Bar getBar() {
if (_barInstance == null) {
synchronized(this) { // or synchronized(someLock)
if (_barInstance == null) {
Bar newInstance = new Bar();
// possible additional initialization
_barInstance = newInstance;
}
}
}
return _barInstance;
}
}
I wonder if absence of volatile
is a serious error or just a slight imperfection with possible performance drawback assuming _barInstance
accessed only through getBar
.
My idea is the following: synchronized
introduces happens-before relation. The thread that initializes _barInstance
writes its value to the main memory leaving the synchronized block. So there will be no double initialization of _barInstance
even when it isn't volatile
: other threads have null
in theirs local copies of _barInstance
(get true
in the first check), but have to read the new value from the main memory in the second check after entering the synchronized block (get false
and do no re-initialization). So the only problem is an excessive one-per-thread lock acquisition.
As I understand, it's correct in CLR and I believe it's also correct in JVM. Am I right?
Thank you.
Not using volatile may result in errors in the following case:
getBar()
and finds _barInstance
to be null
Bar
object and update the reference to _barInstance
. Due to certain compiler optimisations, these operations may be done out of order.getBar()
and sees a non-null _barInstance
but might see default values in member fields of the _barInstance
object. It essentially sees a partially constructed object but the reference is not null.The volatile
modifier will prohibit a write or read of the variable _barInstance
with respect to any previous read or write. Hence, it will make sure that thread 2 will not see a partially constructed object.
For more details: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With