单例模式双重检查(DCL)引发的多线程问题

首先先看一个使用双重检查的单例模式:

public class DoubleCheckedLock{

    private static DoubleCheckedLock instance;

    public static DoubleCheckedLock getInstance(){

        if(instance == null){

            synchronized(DoubleCheckdLock.class)

            if(instance == null){

                instance = new DoubleCheckedLock();

            }

        }

        return instance;

    }

}

双检锁机制的出现确实是解决了多线程并行中不会出现重复new对象,而且也实现了懒加载,但很遗憾的是              instance = new DoubleCheckedLock()在编译器下实现是有过程的

过程1.    给新的实体instance分配内存

过程2.    调用DoubleCheckedLock的构造函数给instance初始化

过程3.    将incetance指向分配的内存空间

在这三个过程之间,由于JVM的“优化”机制,如果出现多线程并发访问的情况,就会出现A线程在执行过程2的时候,已经分配好了内存,此时想要进入过程3,不巧的是,线程B进入了过程2,此时instance并不为null(内存已经被分配),导致线程B此时不执行创建对象的语句,改为直接返回一个未初始化的DoubleCheckedLock对象!

可以使用volatile关键字来定义该变量的语义,使得每次修改instance后,线程工作内存强制刷新到主存中,禁止了JVM的指令重排序,防止了该问题

使用volatile另一个方面则使instance对于其他线程可见,这里被锁住的是DoubleCheckedLock.class而非instance,如果不使用volatile,则有可能引发当前变量更改后只存在于自身线程的工作内存中(即未同步到主存)而引发的多个线程创建多个实例的后果,导致单例模式失去意义。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,378评论 11 349
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,780评论 18 399
  • 小Z是一个初入社会的女孩子,挣着月薪2k的微薄收入,在繁华的市中心上班,每月除了房租和吃饭,基本没有结余。可是,她...
    霁雨初晴阅读 317评论 0 0
  • 2017年就要来了 期末考试也临近了 每个同学都想过个好年 考个不错的成绩 压力随之而来 不同星座的同学都有 自己...
    032d6846533c阅读 509评论 0 0