完整版单列模式的讲解,从网站上找过来的,方便自己以后学习
在网上找了些资料,一个完整版的单列模式,以及对double_clicked_locking的讲解
原文:http://kenwublog.com/explain-java-memory-model-in-detail
In software engineering, double-checked locking (also known as "double-checked locking optimization[1]".) is a software design pattern used to reduce the overhead of acquiring a lock by first testing the locking criterion (the "lock hint") without actually acquiring the lock. Only if the locking criterion check indicates that locking is required does the actual locking logic proceed.
The pattern, when implemented in some language/hardware combinations, can be unsafe. It can therefore sometimes be considered to be an anti-pattern.
It is typically used to reduce locking overhead when implementing "lazy initialization" in a multi-threaded environment, especially as part of the Singleton pattern. Lazy initialization avoids initializing a value until the first time it is accessed.
Consider, for example, this code segment in the Java programming
language as given by [3] (as well as all other Java code segments):
Intuitively, this algorithm seems like an efficient solution to the problem. However, this technique has many subtle problems and should usually be avoided. For example, consider the following sequence of events:
Thread A notices that the value is not initialized, so it obtains the lock and begins to initialize the value. Due to the semantics of some programming languages, the code generated by the compiler is allowed to update the shared variable to point to a partially constructed object before A has finished performing the initialization. Thread B notices that the shared variable has been initialized (or so it appears), and returns its value. Because thread B believes the value is already initialized, it does not acquire the lock. If B uses the object before all of the initialization done by A is seen by B (either because A has not finished initializing it or because some of the initialized values in the object have not yet percolated to the memory B uses (cache coherence)), the program will likely crash.
One of the dangers of using double-checked locking in J2SE 1.4 (and earlier versions) is that it will often appear to work: it is not easy to distinguish between a correct implementation of the technique and one that has subtle problems. Depending on the compiler, the interleaving of threads by the scheduler and the nature of other concurrent system activity, failures resulting from an incorrect implementation of double-checked locking may only occur intermittently. Reproducing the failures can be difficult.
As of J2SE 5.0, this problem has been fixed. The volatile keyword now ensures that multiple threads handle the singleton instance correctly. This new idiom is described in [4]:public class FinalWrapper<T>{ public final T value; public FinalWrapper(T value) { this.value = value; }} public class Foo{ private FinalWrapper<Helper> helperWrapper = null; public Helper getHelper() { FinalWrapper<Helper> wrapper = helperWrapper; if (wrapper == null) { synchronized(this) { if (helperWrapper ==null) helperWrapper = new FinalWrapper<Helper>( new Helper() ); wrapper = helperWrapper; } } return wrapper.value; }
The local variable wrapper is required for correctness. Performance of this implementation is not necessarily better than the volatile implementation.
Java内存模型详解[url=]Java偏向锁实现原理(Biased Locking)[/url]java并发编程实践笔记Java轻量级锁原理详解(Lightweight Locking)volatile原理与技巧从JVM并发看CPU内存指令重排序(Memory Reordering)