正确使用同步单身?

Dan*_*low 10 java singleton multithreading synchronized

因此,我正在考虑建立一个业余爱好项目,一种类似的东西,只是为了了解我的编程/设计.

它基本上是一个多线程的Web蜘蛛,更新相同的数据结构对象 - > int.

因此,为此使用数据库绝对有点过分,我唯一能想到的是用于包含我的数据结构的线程安全单例.http://web.archive.org/web/20121106190537/http://www.ibm.com/developerworks/java/library/j-dcl/index.html

我应该注意一个不同的方法吗?

Ste*_*Kuo 30

双重检查锁定已被证明是不正确和有缺陷的(至少在Java中).出于确切原因,请搜索或查看维基百科的条目.

首先是程序的正确性.如果您的代码不是线程安全的(在多线程环境中),那么它就会被破坏.在性能优化之前,首先是正确性.

要正确,你必须同步整个getInstance方法

public static synchronized Singleton getInstance() {
   if (instance==null) ...
}
Run Code Online (Sandbox Code Playgroud)

或静态初始化它

private static final Singleton INSTANCE = new Singleton();
Run Code Online (Sandbox Code Playgroud)


eri*_*son 10

在Web爬网程序中对数据库使用延迟初始化可能不值得.延迟初始化增加了复杂性和持续的速度命中.一个合理的案例是,很有可能永远不需要数据.此外,在交互式应用程序中,它可用于减少启动时间并提供速度幻觉.

对于像web-crawler这样的非交互式应用程序,它肯定需要立即存在其数据库,懒惰初始化是不合适的.

另一方面,Web爬虫很容易并行化,并且可以从多线程中受益匪浅.使用它作为掌握java.util.concurrent图书馆的练习将是非常值得的.具体来说,查看ConcurrentHashMapConcurrentSkipListMap,这将允许多个线程读取和更新共享映射.

当您摆脱延迟初始化时,最简单的Singleton模式是这样的:

class Singleton {

  static final Singleton INSTANCE = new Singleton();

  private Singleton() { }

  ...

}
Run Code Online (Sandbox Code Playgroud)

关键字final是关键所在.即使您为static单例提供"getter"而不是允许直接字段访问,使单例final有助于确保正确性并允许JIT编译器进行更积极的优化.