开发者

Can Semaphore use the double check locking idiom safely?

Is the following Thead Safe in java?

public class TestDCL{
    private static final Semaphore lock = new Semaphore(1);
    private Object instance;

    public Object m(){
        if(instance == null){
            lock.acquire();
            if(instance == null){
                instance = new Object();
            }
            lock.release();
        }
        return insta开发者_开发知识库nce; 
    }
}


This is not thread-safe. The statement new Object(); is not an atomic operation. instance ceases to be null when memory is allocated for it. A new thread that arrives at the first if condition after memory is allocated for instance, but before its constructor is called will return a partially constructed object. If you are trying to implement a thread-safe singleton, use Bill Pugh's solution which is both thread-safe and lazy.


Agree with previous posts from Tim. Volatile makes for visibility and the reason double check locking has been described as clever but broken is around partially constructed objects (cache coherence/JVM optimisations).

It's all in the Goetz book as Tim suggests but I wanted to raise a point around lazy initialisation. Why do it? In my experience its generally not needed and it you're running in a multithreaded context and really concerned about intialisation safety - you've introduced a lot of variability and complexity which is really hard to test.

I'd also emphasis the old warning not to optimise early. Do you know for a fact that coarse grained synchronisation slows the app down? Usually, its the contention of locks that is slow not the syncrhonization keyword per-sa. A quick test with syncrhonized and DCL would confirm.


The answer is, it depends. Is your instance mutable or immutable? If instance contains mutable state then you must declare it to be volatile. The reason you must due this has nothing to do with partially constructed objects as @Vijay Mathew suggests, but instead to do with thread visibility. Changes made to the state of your singleton instance in one thread will not necessarily be visible to another thread. Using the volatile keyword ensures that the hardware will use some mechanism to flush the cache to eliminate stale data.

Java Concurrency in Practice, chapter 16.2.3 outlines Safe initialization idioms and contains a lazy initialization idiom. 16.2.4 discusses the double-check locking idiom.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜