Is it feasible for Java to check locking by forcing synchronization twice?
I've read everything about double check locking fixes that will never work. I don't like delayed initialization, but it's good to be able to fix legacy code, and such problems are too tempting to try to solve
Here is my example: private int timessafelygotten = 0; private Helper helper = null;
public getHelper() { if (timesSafelyGotten < 1) { synchronized (this) { if (helper == null) { helper = new Helper(); } else { timesSafelyGotten++; } } } return helper; }
In this way, the synchronization code must be run once to create the helper, and once the helper is obtained for the first time, in theory, timessafelygotten can only be incremented after the synchronization code of the helper is created releases the lock and the helper must complete initialization
I don't see any problems, but it's simple and looks incredible. What do you think?
Caleb James DeLisle
Solution
Without a memory barrier (synchronization, volatile, or equivalent from java.util.concurrent), a thread may see another thread's operations in a different order than they appear in the source code
Since there is no memory barrier on the reading of timessafelygotten, you can see that timessafelygotten is incremented before allocating helper in another thread This will result in null being returned from the method
In fact, during unit testing, this may apply to many architectures But this is not true and will eventually fail somewhere
Double check locking now works, but it's tricky to achieve it correctly and quite expensive The deferred initialization mode is less fragile, easier to read, and does not require any exotic flavor