马士兵:(美团面试题)单例DCL要不要加Volatile-看视频记笔记

报名入口来源:中国教育在线 2022-05-31

马士兵:(美团面试题)单例DCL要不要加Volatile?-看视频记笔记

马士兵:(美团面试题)单例DCL要不要加Volatile?-看视频记笔记

 

视频地址:西瓜视频,标题是 大白话带你从使用到源码透彻解析线程池

问题1 用三个线程,按顺序输出ABC

 

    看起来简单,实际很多坑。

 

答:

ReentrantLock lock = new ReentrantLock();

synchronized不同,synchronized对象锁队列只有一个,里面的等待线程是无序的,调用notify时不能保证下一个唤醒的线程是哪个,ReentrantLock可以new多个Condition条件队列,可以区分出不同的线程类型(如生产者、消费者)

 

同时当调用线程start执行方法时线程进入的是就绪状态,ABC不线程一定会按顺序执行。所以要配合CountDownLatch闭锁,相当于线程前的一扇大门,当为0时大门才打开,之后线程将不受闭锁控制。

 

    闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成。

 

问题2 cpu指令乱序

 

为了提高效率,cpu执行指令时可能打乱顺序,注:但是在单线程时cpu保证不会影响最终数据一致性

问题3 this逸出

 

对象的创建过程:1new 分配空间,初始化成员变量的默认值 ,如int类型是0 2、调用构造方法,初始化值 》3、变量名和内存空间建立关键

 

一旦在构造方法中使用多线程时,可能造成指令重排,另一个线程获取到的值就可能是0。因为执行构造方法和变量名地址关联步骤反过来了,于是先得到了对象,但还没有执行完构造方法,线程访问到的值就是默认值。

 

    原则:不要在构造方法中启动线程

 

美团面试题

1 解释一下对象的创建过程

 

new 分配内存空间,成员赋默认值

调用对象构造方法,初始化成员变量

变量名和内存空间建立联系

2 单例DCL(double check lock)要不要加volatile(指令重排)

 

发生指令重排时,得到的是一个半初始化状态的对象,使用的里面的成员变量都是默认值!!所以需要volatile,给变量建立内存屏障,禁止cpu进行指令重排。

我的题库在线题库
近期直播
联系方式

预报名

咨询

课程

题库