• 单例模式


    众所周知(也许有些人不知道),编译器以及CPU会在不影响串行结果的情况下对代码进行重排序,以便加快执行速度。(比如超标量流水线技术)

    这在并发执行中会造成一些问题。以单例模式的DCL写法举例:

    public class Singleton{

      private Singleton(){};

      public static volatile Singleton singleton;

      public static Singleton getSingleton(){

        if(singleton == null){

          synchronized(singleton){

            if(singleton == null){

              singleton = new Singleton();

            }

          }

        }

        return singleton;

      }

    }

    双重检查加锁好理解,一是为了保证单一实例,而是为了减少并发开销。为什么又用了volatile了呢?

    因为橙色标注的部分实际上有三步:

    分配内存,初始化对象, 引用赋值。

    但由于重排序的存在,有可能会先分配内存,然后赋值,最后才初始化。并发下就有可能将未初始化的对象暴露出来。这也是为什么要用volatile的原因。

    jdk1.5后, volatile语义中有了happen-before关系约束。保证了对volatile对象的写操作,一定在对其后续的读操作前完成。

    也就杜绝了这种重排序造成错误的情况。

  • 相关阅读:
    C# SuperWebSocket服务端学习(二)
    C# SuperSocket服务端入门(一)
    C# SuperWebSocket服务端、客户端学习(三)
    皮尔逊相关系数和余弦相似性的关系
    各种定向方式的对比-有图
    查看Linux的CPU信息,核数等
    临时表空间
    优化临时表使用,SQL语句性能提升100倍
    Java中线程池的学习
    android面试题之六
  • 原文地址:https://www.cnblogs.com/zqiguoshang/p/6628701.html
Copyright © 2020-2023  润新知