Java Double Checked Locking

Double Checked Locking in Singleton

No, since you are obtaining lock on the SearchBox.class, only one thread will enter the synchronized block at a time. So the first thread enters then finds searchBox is null and creates it and then leaves the synchronized block, then the second thread enter the block then it finds that the searchBox is not null because the first thread already created it so it will not create a new instance of searchBox.

The double checked pattern is used to avoid obtaining the lock every time the code is executed. If the call are not happening together then the first condition will fail and the code execution will not execute the locking thus saving resources.

Convert double check locking from using synchronized to locks in JAVA

Transformation of synchronized blocks to the equivalent block using ReentrantLock is pretty rote.

First you create a lock with the same or similar scope and lifetime as the object you were locking on. Here you are locking on MyClass.class, hence a static lock, so you can map this to a static lock in MyClass, such as MyClass.initLock.

Then just replace each:

synchronized (object) {

with

lock.lock();
try {

and each associated closing brace with

} finally {
lock.unlock();
}

Putting it all together you have:

private final static ReentrantLock initLock = new ReentrantLock();

private static void redoHeavyInitialisation() {
if (needToReinitialise()) {
MyClass.initLock.lock();
try {
if (needToReinitialise()) {
doHeavyInitialisation();
}
} finally {
MyClass.initLock.unlock();
}
}
}

Performance-wise there is little daylight between the approaches. They essentially have the same semantics and usually use similar underlying mechanisms. In the past, there have been performance differences - sometimes optimizations have gone in that affect one or the other, so on some JVMs you can find a difference, but the whole point of double checked locking is to avoid taking the lock anyway, so just do what's simplest. You only get the lock for a very small transitory period while the needToReinitialise() method is running, so the locking cost won't have any ongoing impact.

Double-checked locking without volatile

First things first: what you are trying to do is dangerous at best. I am getting a bit nervous when people try to cheat with finals. Java language provides you with volatile as the go-to tool to deal with inter-thread consistency. Use it.

Anyhow, the relevant approach is described in
"Safe Publication and Initialization in Java" as:

public class FinalWrapperFactory {
private FinalWrapper wrapper;

public Singleton get() {
FinalWrapper w = wrapper;
if (w == null) { // check 1
synchronized(this) {
w = wrapper;
if (w == null) { // check2
w = new FinalWrapper(new Singleton());
wrapper = w;
}
}
}
return w.instance;
}

private static class FinalWrapper {
public final Singleton instance;
public FinalWrapper(Singleton instance) {
this.instance = instance;
}
}
}

It layman's terms, it works like this. synchronized yields the proper synchronization when we observe wrapper as null -- in other words, the code would be obviously correct if we drop the first check altogether and extend synchronized to the entire method body. final in FinalWrapper guarantees iff we saw the non-null wrapper, it is fully constructed, and all Singleton fields are visible -- this recovers from the racy read of wrapper.

Note that it carries over the FinalWrapper in the field, not the value itself. If instance were to be published without the FinalWrapper, all bets would be off (in layman terms, that's premature publication). This is why your Publisher.publish is disfunctional: just putting the value through final field, reading it back, and publishing it unsafely is not safe -- it's very similar to just putting the naked instance write out.

Also, you have to be careful to make a "fallback" read under the lock, when you discover the null wrapper, and use its value. Doing the second (third) read of wrapper in return statement would also ruin the correctness, setting you up for a legitimate race.

EDIT: That entire thing, by the way, says that if the object you are publishing is covered with final-s internally, you may cut the middleman of FinalWrapper, and publish the instance itself.

EDIT 2: See also, LCK10-J. Use a correct form of the double-checked locking idiom, and some discussion in comments there.

How to solve the Double-Checked Locking is Broken Declaration in Java?

Here is the idiom recommended in the Item 71: Use lazy initialization judiciously of
Effective Java:

If you need to use lazy initialization for performance on an
instance field, use the double-check
idiom
. This idiom avoids the cost
of locking when accessing the field
after it has been initialized (Item
67). The idea behind the idiom is to
check the value of the field twice
(hence the name double-check): once
without locking, and then, if the
field appears to be uninitialized, a
second time with locking. Only if the
second check indicates that the field
is uninitialized does the call
initialize the field. Because there is
no locking if the field is already
initialized, it is critical that the
field be declared volatile (Item
66). Here is the idiom:

// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;

private FieldType getField() {
FieldType result = field;
if (result != null) // First check (no locking)
return result;
synchronized(this) {
if (field == null) // Second check (with locking)
field = computeFieldValue();
return field;
}
}

This code may appear a bit convoluted.
In particular, the need for the local
variable result may be unclear. What
this variable does is to ensure that
field is read only once in the common
case where it’s already initialized.
While not strictly necessary, this may
improve performance and is more
elegant by the standards applied to
low-level concurrent programming. On
my machine, the method above is about
25 percent faster than the obvious
version without a local variable.

Prior to release 1.5, the double-check
idiom did not work reliably because
the semantics of the volatile modifier
were not strong enough to support it
[Pugh01]. The memory model introduced
in release 1.5 fixed this problem
[JLS, 17, Goetz06 16]. Today, the
double-check idiom is the technique of
choice for lazily initializing an
instance field. While you can apply
the double-check idiom to static
fields as well, there is no reason to
do so: the lazy initialization holder
class idiom is a better choice.

Reference

  • Effective Java, Second Edition

    • Item 71: Use lazy initialization judiciously

Why is volatile used in double checked locking

A good resource for understanding why volatile is needed comes from the JCIP book. Wikipedia has a decent explanation of that material as well.

The real problem is that Thread A may assign a memory space for instance before it is finished constructing instance. Thread B will see that assignment and try to use it. This results in Thread B failing because it is using a partially constructed version of instance.

Is double-checked locking only broken in a lazy initialization scene?

Answer to your 1: Yes. From Java 5 class loader guarantees the single or one time initialization for static fields.
Answer to your 2: From code its not clear but it depends what you reading in wxMpConfigStorage.isJsapiTicketExpired() method. If you deciding based on reading something which is not thread safe then yes DCL can fail. But in your case jsapiTicketExpiresTime is volatile and so thread safe to read and so DCL will work for you.

Double checked locking for static fields in java

Assuming you are using Java 5 or later1, the above code is thread-safe2.

It doesn't matter that either the method or field is static provided that:

  1. field being initialized is volatile and,
  2. the code doing the DCL initialization is using the same mutex object for any given field.

The former is obviously true. The latter is true because all calls to getField4() are locking the same Class object.

1 - Prior to Java 5, the specified semantics of volatile are not sufficient to guarantee that the code is thread-safe.

2 - Thread-safe but ugly. It is better to avoid the DCL idiom and use one of the other alternatives.



I cannot make the method static method ...

I don't see why not. It is private so you should not be constrained as to whether it is a static or instance method. It should only affect the current class.

But as noted above, it doesn't make any difference to the idiom.



Related Topics



Leave a reply



Submit