六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 27|回复: 0

Singleton

[复制链接]

升级  86.67%

52

主题

52

主题

52

主题

秀才

Rank: 2

积分
180
 楼主| 发表于 2013-2-7 16:03:07 | 显示全部楼层 |阅读模式
第一个问题,Singleton模式在多线程环境为何遭遇困境?答案是,采用lazy initialization策略时,如果没有合理的同步(synchronize),各个线程得到的实例可能不是同一个。详情可以参考JavaWorld 2001年的文章:When Is A Singleton Not A Singleton。(某些同志连这篇文章都没听说过,居然也可以抱怨说“找不到这方面的英文资料”,恩,我们说话恐怕还是谦虚谨慎点好。)


public class MyClass {  private static MyClass _instance;  public static MyClass getInstance() {    if(_instance != null) {      _instance = new MyClass();    }    return _instance;  }


如果有两个线程同时调用MyClass.getInstance()方法,就有可能造成MyClass的构造子被调用两次。所以我们需要同步――准确说,恰当的同步。在C++里面有一种常见的Singleton实现策略叫Double Checked Locking idiom(http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton_p.html,listing 6),但这种实现策略在Java中不生效(这是由于JVM的本性造成的,详情请看这篇文章:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html ),因此如果要在Java中实现lazy initialization策略的Singleton,你就必须采取保守的同步策略,也就是:



public static synchronized MyClass getInstance() {  ...}


如果采取保守的同步策略(将整个getInstance()方法同步),多个线程需要获得Singleton实例时就必须在getInstance()方法上排队等待。这就是传说中的“Singleton模式的性能问题”。现在我要提问了:这种性能问题在什么情况下才会出现?

答案就摆在你面前:只有采用lazy initialization策略时,才会存在这样的性能问题。那么如果放弃lazy initialization策略、改用eager initialization策略(即:预先创建好Singleton实例),Singleton模式还会存在这样的性能问题吗?我们把上面的例子改成eager initialization策略看看:


public class MyClass {  private static MyClass _instance = new MyClass();  public static MyClass getInstance() {    return _instance;  }


我请问,这样的一个Singleton难道还会有什么“性能问题”吗?它付出的代价是更长的初始化时间,获得的收益则是更快并且线程安全的实例获得,而这正是Spring容器对其管理的组件的默认策略。其实这个问题早已有了定论,请看http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton_p.html这篇文章的listing 1和listing 2,Singleton模式的两种正确的实现策略早在2001年就已经讨论清楚了。

作为结论,我提醒某些善于过度简化乃至以讹传讹的高手们:请不要简单地说一句“Singleton模式有性能问题”了事。完整的说法应该是,当采用Lazy Initialization策略时,如果需要经常地获取Singleton实例,则Singleton模式中用于获取实例的方法有可能成为性能瓶颈;如果条件允许采用Eager Initialization策略,则Singleton模式不会带来任何额外的性能开销――如果考虑管理对象池或是新建对象实例的性能开销,Singleton模式能够提升系统的性能。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表