分享

你真的了解单例模式吗?你真的认为单例模式很简单吗? 第二篇

 昵称2byn1 2016-08-30

接着说我们的单例故事。
想要解决上面的线程不安全问题,有很多种办法,这里我们一一来探讨。
第一种就是通过synchronized来控制线程安全,将synchronized加在getInstance方法上,
public static synchronized SingleFactory getInstance()
运行下之前的main方法,是不是发现hashCode都一样了?开心吧,这么严重的问题一下子就解决了。
~~~~
再来一盆冷水:
这种做法其实效率很低。因为在任何时候只能有一个线程调用该方法,其余的需要加入等待,阻塞程度可想而知,如何解决这个问题呢?
我们来分析下,一般这种单例模式都会用在什么场合?是不是初始化的时候?
好的,我们姑且就认为是初始化的时候,即第一次调用的时候创建对象,后续只存在调用的操作。那么就印出来我们之前提到的双重检验
锁。

双重检验锁
双重检验锁(double checked locking pattern),是一种使用同步块加锁的方法。之所以称之为双重检验锁,是
因为会有两次检验 instance == null 的操作。一次是在同步块外面,一次是在里面。
先来上代码:

public static SingleFactory getInstance() {
    if (instance == null) {
        synchronized (SingleFactory.class) {
            if (instance == null) {
                instance = new SingleFactory();
            }
        }
    }
    return instance;
}


运行后是不是发现也ok?
好了,我们来说一下为什么要在同步块外面一次,里面又来一次。
因为当我们第一次初始化的时候,可能会有多个线程同时进入外部的if判断中,如果这个时候没有对当前类进行同步块加锁,则很容易就出现多
个实例的状态。因此我们需要在外面做次判断,然后判断里面加上一个同步块。

~~~~
再来一盆冷水。
为啥?上面的代码看起来很严谨,很完美啊,为什么还是不对?

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多