|
|
Double-checked Locking (DCL) and how to fix itThe term double-checked locking (and sometimes the initials DCL) is used to refer to an infamous programming "pattern" which attempts to avoid synchronization when reading the reference to a singeton instance that is constructed through lazy initialisation (that is, it is not constructed until it is first required). An implemenation using synchronization would be:
public class MyFactory {
private static MyFactory instance;
public synchronized static MyFactory getFactory() {
if (instance == null)
instance = new MyFactory();
return instance;
}
}
The above pattern is perfectly correct. However, some programmers have been reluctant to use it because on all reads it makes a synchronized access and "synchronization is slow". Spurred by this general fear of "slow synchronization", a popular idiom was to attempt to avoid the synchronization on the read as follows:
public class MyBrokenFactory {
private static MyFactory instance;
private int field1, field2 ...
public static MyBrokenFactory getFactory() {
// This is incorrect: don't do it at home, kids!
if (instance == null) {
synchronized (MyBrokenFactory.class) {
if (instance == null)
instance = new MyFactory();
}
}
return instance;
}
private MyBrokenFactory() {
field1 = ...
field2 = ...
}
}
On modern JVMs, this optimisation– even if it were correct– is probably no longer that useful. Unfortunately, it's also incorrect. We can show it's incorrect by considering what might happen by two threads that are concurrently calling MyBrokenFactory.getFactory():
So how do we fix the double-checked locking "antipattern"? On the next page, we look at options for fixing double-checked locking. Did this article answer your question? If not, visit the new
Javamex discussion forums to ask your question.
Copyright © Javamex UK 2009. All rights reserved. |