zoukankan      html  css  js  c++  java
  • DCL-单例模式的线程安全

    DCL-Double Check Lock

    双端检锁机制

    传统单机环境下的单例模式

    public class Test002 {
    
        private static Test002 instance = null;
    
        private Test002(){
            System.out.println(Thread.currentThread().getName() + "	这是一个构造器" );
        }
    
        public static Test002 getInstance(){
            if(instance == null){
                instance = new Test002();
            }
    
            return instance;
        }
    
        public static void main(String[] args) {
            System.out.println(Test002.getInstance() == Test002.getInstance());
            System.out.println(Test002.getInstance() == Test002.getInstance());
            System.out.println(Test002.getInstance() == Test002.getInstance());
        }
    }
    

    输出结果

    多线程环境下

    public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                  Test002.getInstance();
                },String.valueOf(i)).start();
            }
        }
    

    输出结果

    解决方法

    传统可以加sync,但是sync是重锁,存在很大的弊端,直接把整个方法getInstance()加锁了
    所以我们采用DCL-双端检锁机制,只给代码块加sync

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

    但是这样会出现指令重排,高并发多线程环境下,底层会对指令进行优化,导致顺序发生改变,可能会出现问题
    原因是某一个线程执行到第一次检测时,读取到的instance不为null时,instance的引用对象可能还没有完成
    初始化(但是内存已经被分配出去了)

    instance = new Instance()可以分成以下三步:

    memory = allocate();// 1.分配对象内存空间
    instance(memory);// 2.初始化对象
    instance = memory;// 3.设置instance指向刚刚分配的内存地址,此时instance!=null;
    

    步骤2,3不存在数据依赖关系,所以可以进行重排优化
    因此,需要加volatile修饰

    private static volatile Test002 instance = null;
    
  • 相关阅读:
    对软件工程课程的期望
    自我介绍
    新目标
    课后作业-阅读任务-阅读笔记-4
    20150914-构建之法:现代软件工程-阅读笔记
    团队编程项目作业2-团队编程项目开发环境搭建过程
    团队编程项目作业2-团队编程项目设计文档
    个人-GIT使用方法
    结对编程项目作业2-结对编项目设计文档
    结对编程项目作业2-开发环境搭建过程
  • 原文地址:https://www.cnblogs.com/zhangyuanbo/p/14188532.html
Copyright © 2011-2022 走看看