面试官超级喜欢问的JMM和Volatile

前言

自学了一年JAVA阿巴阿巴终于约到了面试,这次面试官让她谈谈对JMM和volatile的理解。

面试官: 了解JMM吗,讲一下JMM。

阿巴阿巴: 知道一些,JMM是JAVA内存模型(JAVA Memory Model),目的是为了屏蔽各种硬件和操作系统之间的内存访问差异,从而让JAVA程序在各种平台对内存的访问一致。

阿巴阿巴: 不仅如此,JMM还规定了所有的变量都存储在主存中,每个线程都有自己独立的工作空间,线程对变量的操作必须先从主存中读取到自己的工作内存中然后再进行操作,最后回写回主存。

阿巴阿巴: 关于主存和工作内存的交互JAVA定义了八种操作来完成,且这些操作都是原子性的:lock、unlock、read、load、use、assign、store、write

面试官: 不错不错,那JMM是真实存在的嘛,和JVM内存模型(JAVA 虚拟机内存模型)是一样的嘛?

阿巴阿巴: 不是真实存在的,JMM讲的也只是一种模型,真实的实现可能还是和模型会有差异的。JMM和JVM是不一样的,它们并不是同一个层次的划分,基本上没啥关系。

堆和方法区是线程共享的,虚拟机栈、本地方法栈、程序计数器是线程私有的

程序计数器是这几块区域唯一一个不会发生OOM的区域

面试官: 理解的还不错嘛,那你讲讲Volatile关键字呗

阿巴阿巴: Volatile可以说是JAVA虚拟机提供的最轻量级的同步机制,当一个变量被定义为volatile后,它将具备俩种特性,第一个是保证此变量对所有线程的可见性,即当一个线程改变了这个变量的值后,其他线程能够立即感知的到,虽然具有可见性,但是多线程在并发情况下对volatile修饰的变量进行操作时是会有线程安全性的问题的。这是因为volatile修饰的变量在各个线程工作内存中是不存在一致性的,但是由于每次使用都要进行刷新,导致执行引擎看不到不一致的情况。

阿巴阿巴: Volatile修饰的变量的第二个特性是禁止指令重排序优化,普通的变量仅仅会保证在该方法的执行过程中所有依赖的赋值结果的地方都能够获取到正确的结果。而不能保证赋值的顺序和代码中的书写顺序一致。例如下面的DCL的单例模式。

public class Instance {
    private String str = "";

    private volatile static Instance ins = null;
    /**
     * 构造方法私有化
     */
    private Instance(){
        str = "hi";
    }

    /**
     * DCL获取单例
     * @return      */
    public static Instance getInstance(){
        if (ins == null){
            synchronized (Instance.class){
                if (ins == null){
                    ins = new Instance();
                }
            }
        }
        return ins;
    }
}

阿巴阿巴: 如果上面ins变量不使用volatile变量进行修饰,那么当线程A在获取了Instance.class锁后,对ins变量进行 ins = new Instance() 初始化时,由于这是很多条指令,jvm可能会乱序执行。这个时候如果线程B在执行if (ins == null)时,正常情况下,如果为true,说明需要获取Instance.class锁,等待初始化。但是这时候,假设线程A再没有对ins进行初始化完,比如只分配了空间,对象还没构造完,但是已经将引用返回了,这样线程B得到的就是一个未能实例化完全的对象,从而发生异常。而加了volatile关键字后,如果实例还未初始化完成,那么它的引用是不会向外发布的,这样即可避免异常的发生。

面试官: 不错,你这块都掌握的挺扎实的,明天可以来上班了。

阿巴阿巴: 好的😈


#java求职##Java##学习路径#
全部评论
写的很好,可以直接用的
点赞 回复 分享
发布于 2022-02-26 23:50

相关推荐

不愿透露姓名的神秘牛友
04-10 11:57
1. Guava Cache 和 Caffeine 分别使用了什么缓存淘汰算法​2. 实际项目里本地缓存命中率大概多少​3. 引入缓存带来的风险和解决方案​4. 缓存的读写策略​5. 如何保证缓存和数据库一致性​6. “先写缓存,再异步批量刷库”方案,除一致性外还有哪些潜在风险​7. 如何拦截恶意请求,设计防护手段避免缓存被恶意利用​8. 布隆过滤器原理,如何解决缓存穿透​9. 布隆过滤器误判概率大概多少,如何估计​10. 定时任务 5 分钟一轮询,任务执行超 5 分钟时,如何保证状态不丢失、不阻塞调度​11. 分布式 RPC 为什么要自定义协议,而不用 HTTP​12. 单机 QPS 1w+ 这个数据是怎么统计/得到的​13. RPC 项目目前瓶颈在哪​14. 了解哪些 HTTP 版本,各版本特性​15. HTTP 队头阻塞是什么​16. 队头阻塞是否只存在于 HTTP 层面​17. TCP 会不会存在对应阻塞问题​18. HTTP3 如何解决 HTTP2 在 TCP 上的队头阻塞​19. 为什么 HTTP3 基于 QUIC,而不继续在 TCP 上优化​20. TCP 如何实现可靠传输和流量控制​21. TCP 发送窗口如何根据接收窗口和拥塞情况动态调整,窗口结构如何维护变化​22. TCP 如何判断报文丢失,什么条件触发重传​23. TCP 除重传计时器外还有哪些计时器​24. AI 项目中降低大模型幻觉的具体优化方法​25. 大模型产生幻觉的底层技术原因​26. 算法题:Java 原生数组实现栈,实现常用操作
查看26道真题和解析
点赞 评论 收藏
分享
评论
6
26
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务