这是我参与「掘金日新计划 · 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的分解,我们需要具体知道她的本质 就是数据可见性,且不保证原子性的一个特例,在多线程并发过程中会很受用这些东西
所以在我们具体开发的过程中,对于基础的数据,我们可以进行具体的展示 如果是两个线程都会用到的局部变量,这就要用到这个关键字去保证数据的可见性了