面试官的一道简单的单例模式问题给我问懵了,详解单例模式面试官的一道简单的单例模式问题给我问懵了,详解单例模式
双重检查加锁为什么要加双重检查加锁为什么要加volatile关键字!关键字!
目录目录
1.场景:场景:
2.对象的创建过程对象的创建过程
3.指令重排指令重排
4.CPU执行时间片执行时间片
5.指令重排对双重检查加锁模式的影响指令重排对双重检查加锁模式的影响
1.场景:场景:
面试官:有用过单例模式吗?
我:有有有(自信满满)。
面试官:说说单例模式几种写法?
我:懒汉式和饿汉式,懒汉式巴拉巴拉,饿汉式巴拉巴拉。
面试官:我们都知道synchronized加锁是比较耗费资源的,你这种写法每次访问都需要获得锁(基础的懒汉式写法),效率比
较低,有什么优化的方式吗?
我:沉思片刻,脑海灵光一现。可以采用双重检查加锁的方式,巴拉巴拉。(还好之前看到过,暗自庆幸)
面试官:为什么双重检查加锁需要加volatile关键字?
我:要不我们问问度娘?
在回答这个问题之前我们要明确这几点,一个是对象的创建过程,一个是什么是指令重排,一个是CPU时间片的概念,一个
是synchronized不会禁止指令重排,最后一个是volatile禁止指令重排。
2.对象的创建过程对象的创建过程
对象的创建过程主要分成三步,如下图展示的汇编码所示,主要是0,4,7这三步。
0 这步是为新创建的对象申请内存,但是此时对象中的成员变量的值是默认的值(半初始化),即下图a 的值此时是0;
4 初始化对象,在这步才把10赋给成员变量a
7 建立关联,把testDemo引用和new 出来的TestDemo对象建立关联
public class TestDemo {
private int a = 10;
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
// 0 new #2 申请内存,半初始化,此时a的值是0(当对象刚new出来的时候会给里面的成员变量设置默认初始值,int类型的初始值
是0)
// 3 dup 复制
// 4 invokespecial #3 <company/syncronized/TestDemo.> 初始化,在这步把10赋给a,此时a的值是10
// 7 astore_1 testDemo和new TestDemo()建立关联
// 8 return
}
}
3.指令重排指令重排
指令重排是JMM(java内存模型)中的一个概念,它是指计算机在执行程序时,编译器和处理器会对不存在数据依赖性的指令进
行重新排序。
什么是数据依赖性:就是A,B两个指令,B指令的执行依赖A指令的执行,举个简单的例子,看下面的代码,语句2需要语句1
评论0
最新资源