设计模式【synchronize+volatile双重检查机制的懒汉式单例】

261 阅读2分钟

前言

  • 上文提到了两种懒汉式单例加载问题,针对多线程我提出了一种加锁的方式避免重复实例化。本来以为就解决了问题。虽然测试中我没有发现问题,但是请教了一个老前辈他给我指出了其中的不足。

问题分析

  • 加锁就是让获取对象时能够线性执行。但是因为我们锁是加载if上的。
  • 当A线程获取锁成功时,并且完成了对象的创建后,B线程中对象并没有及时的得到刷新,这个时候B线程也获取到A线程释放的锁了,那么还是会重复创建对象。
  • 这部分就涉及到线程对象都是拷贝在每个线程中的。前辈还说没有遇到问题是因为我运气好。实际上还是存在一定的安全隐患的。

解决方案

  • 其实遇到问题是好事,只有遇到问题才能说明我们有进步的空间,更确切的说我们有进步的机会。如果我们贪图安逸那么只会错失高峰。
  • 上面的问题其实涉及到一个知识点就是Java中线程中对象时如何刷新的。真实对象时在内存中线程中都是在内存中拷贝的一个副本。线程修改对象实际上是修改副本然后回传内存。内存中在分发给各个线程。这个过程就是我们上述的原因出现。
  • volatile关键字就能很好的解决,他能够做到当内存变量出现改变时第一时间刷新最新值。
volatile private static Person person = null;
​
private SingleFactory()
{
}
​
public static Person getIstance()
{
    try
    {
        Thread.sleep(30);
    }
    catch (InterruptedException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    synchronized (SingleFactory.class)
    {
        if (person == null)
        {
            person = new Person();
        }
    }
    return person;
}

总结

  • 一个简单的单例模式我居然能够学到synchronize和volatile两个关键字,简直赚了;关于这两个关键字设计到计算机底层原理,这里我们就不在深入研究了