volatile解构二

114 阅读2分钟

这是我参与「掘金日新计划 · 6 月更文挑战」的第12天 ,点击查看活动详情

四、面试:在哪些场景下遇见volatile?

单例模式:

我们所写的简单经典的:







 class SingletonTest {
    //静态的空对象
    private  static SingletonTest  Instance=null;

    //2.构造器私有化
    private  SingletonTest(){

        System.out.println("构造器创建一个对象");

    }


     //静态的公共方法
    public  static  SingletonTest getSingletonTest(){

        while (Instance==null){

            Instance=new SingletonTest();
        }

        //返回一个对象
        return  Instance;
    }

}


public class SingletonTest1 {

    public static void main(String[] args) {
        //单机版的;
        System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
        System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
        System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());
        System.out.println(SingletonTest.getSingletonTest()==SingletonTest.getSingletonTest());



   //多线程


   for(int i=1;i<10;i++) {

       new Thread(()->{
           SingletonTest.getSingletonTest();
            System.out.println(Thread.currentThread().getName()+SingletonTest.getSingletonTest());
       },String.valueOf(i)).start();
       

       //构造器莫名其妙的输出了很多次--也即是说一个构造器被执行多次; 多线程环境下不行;
   }



    }



}

这个测试环境是在: mian线程中只有简答的线程调用的;

 2.单例模式的DCL(double check Lock)双端检锁机制---》可重复锁

     解决

 public  static  SingletonTest02 getSingletonTest(){

         //2.利用的是dcl的使用同步代码块;

        if (Instance==null){

          synchronized (SingletonTest02.class){
              if (Instance==null){
                Instance=new SingletonTest02();
          }
          }
    }  
    //在加锁前后都要检查
    return Instance;
    }

DCL---可能不安全.因为存在的是一个指令重排的过程

这里我们用的是volatile的解释;

但是DCL:不能保证是绝对安全的所以;

在单例的这个对象前面加入volatil       

  //volatile的作用是禁止重排序
    private  static volatile SingletonTest02  Instance=null;

基于对volatile的分解,我们需要具体知道她的本质 就是数据可见性,且不保证原子性的一个特例,在多线程并发过程中会很受用这些东西

所以在我们具体开发的过程中,对于基础的数据,我们可以进行具体的展示 如果是两个线程都会用到的局部变量,这就要用到这个关键字去保证数据的可见性了