fas*_*ava 9 java concurrency singleton double-checked-locking
为什么模式被认为是破碎的?它看起来很好吗?有任何想法吗?
public static Singleton getInst() {
if (instace == null) createInst();
return instace;
}
private static synchronized createInst() {
if (instace == null) {
instace = new Singleton();
}
}
Run Code Online (Sandbox Code Playgroud)
Jer*_*erg 21
乍一看看起来还不错,但这种技术有许多微妙的问题,通常应该避免.例如,请考虑以下事件序列:
您可以通过使用"volatile"关键字来正确处理单例实例来避免这种情况
Mic*_*rdt 11
整个讨论是一个巨大的,无休止的脑时间浪费.99.9%的时间,单身人士没有任何重大的设置成本,并且没有任何理由设计设置来实现非同步保证延迟加载.
这就是你在Java中编写Singleton的方法:
public class Singleton{
private Singleton instance = new Singleton();
private Singleton(){ ... }
public Singleton getInstance(){ return instance; }
}
Run Code Online (Sandbox Code Playgroud)
更好的是,让它成为一个枚举:
public enum Singleton{
INSTANCE;
private Singleton(){ ... }
}
Run Code Online (Sandbox Code Playgroud)
我不知道它是否被破坏,但由于同步这是相当昂贵的,它不是真正最有效的解决方案.更好的方法是使用'Initialization On Demand Holder Idiom',它在第一次需要时将你的单例加载到内存中,顾名思义,因此延迟加载.使用这个习惯用语最大的好处是你不需要同步,因为JLS确保类加载是串行的.
有关该主题的详细维基百科条目:http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
要记住的另一件事是,由于Spring和Guice之类的依赖注入框架已经出现,这些容器创建和管理类实例,如果需要它们将为您提供Singleton,因此不值得打破你的头脑除此之外,除非你想学习模式背后的想法,这是有用的.另请注意,这些IOC容器提供的单例是每个容器实例的单例,但通常每个应用程序都有一个IOC容器,因此它不会成为问题.
问题如下:您的JVM可能会重新排序您的代码,并且字段对于不同的线程并不总是相同.看看这个:http://www.ibm.com/developerworks/java/library/j-dcl.html.使用volatile关键字应该解决这个问题,但它在java 1.5之前就已经破了.
大多数情况下单次检查锁定的速度已经足够快,请尝试以下方法:
// single checked locking: working implementation, but slower because it syncs all the time
public static synchronized Singleton getInst() {
if (instance == null)
instance = new Singleton();
return instance;
}
Run Code Online (Sandbox Code Playgroud)
另请参阅有效的java,在这里您可以找到关于此主题的精彩章节.
总结一下:不要做双重检查锁定,有更好的idoms.
| 归档时间: |
|
| 查看次数: |
2731 次 |
| 最近记录: |