Java面试官最喜欢问的关键字之volatile详解

 更新时间:2019年03月19日 15:38:08   作者:半亩方田  
这篇文章主要给大家介绍了关于Java面试官最喜欢问的关键字之volatile的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

笔者去年面试过几家公司,基本上每家公司都会问到volatile,甚至有的公司每轮面试的时候都会问到。面试官这么喜欢问volatile就是因为这个关键字涉及到的知识点较多比如Java内存模型、内存屏障、happen-befor等知识,可以继续挖掘到系统指令、超线程等知识。

Java内存模型(JMM)

volatile是Java虚拟机提供的最轻量的同步机制,但很难被正确的理解与使用,通过学习Java内存模型对volatile专门定义的一些特殊访问规则,或许会对理解volatile有一定帮助。

Java内存模型定义了线程和内存之间关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读 / 写共享变量的副本。本地内存是 JMM 的一个抽象概念,并不真实存在;它涵盖内存、缓存、寄存器以及其他的硬件和编译器优化。Java的内存模型抽象如下:

volatile的语义

volatile主要提供了两种语义:

1,可见性:

可见性是指一个线程写入的值,其他线程能够立即读取。在由Java内存模型可知道,每个线程都是有本地内存。所以线程A写入在正常情况下,线程B不能立即读取。但是在volatile变量,可以保证线程A不写入本地内存直接写入主内存,线程B直接从主内存中读取,不从本地内存中读取。

2,禁止指令重排序:

重排序是指编译器和处理器为了优化程序性能而对指令进行重排序的一种优化手段。

Java程序的几种重排序

  • 编译器优化重排序:编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
  • 指令级并行的重排序:如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  • 内存系统的重排序:处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行

volatile的技术基石--内存屏障

内存屏障是cpu指令,该指令保证特定操作的顺序性和某些内存的可见性。插入一条内存屏障指令之后会告诉编译器和CPU:不管什么指令都不能和这条指令重排序。内存屏障所做的另外一件事情就是强制刷出各种CPU cache,如一个Write-Barrier(写入屏障)将刷出所有在Barrier之前写入cache的数据,因此,任何CPU上的线程都能读取到这些数据的最新版本。

对于Java程序而言,如果把加入volatile关键字的代码和未加入volatile关键字的代码都生成汇编代码,会发现加入volatile关键字的代码会多出一个lock前缀指令。

volatile的典型用例

状态标志,代码示例如下:


线程1执行run()的过程中,可能有另外的线程2调用了shutdown,所以stop变量必须是volatile(利用的volatile的可见性)。

还有一种常见的用法在双重检验的单例实现上,代码如下:

instance = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情:

  • 给 instance 分配内存
  • 调用 Singleton 的构造函数来初始化成员变量
  • 将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)

如果instance变量没有加volatile,因为指令重排序的存在,就可能导致执行步骤是1-2-3,也可能是1-3-2。一旦是1-3-2,就可能会导致访问未初始化的内存。但是加上volatile关键字之后,一定保证是按照1-2-3步骤执行的(利用的volatile的禁止重排序)。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • Spring注解Autowired的底层实现原理详解

    Spring注解Autowired的底层实现原理详解

    从当前springboot的火热程度来看,java config的应用是越来越广泛了,在使用java config的过程当中,我们不可避免的会有各种各样的注解打交道,其中,我们使用最多的注解应该就是@Autowired注解了。本文就来聊聊Autowired的底层实现原理
    2022-10-10
  • Java将word文件转成pdf文件的操作方法

    Java将word文件转成pdf文件的操作方法

    这篇文章主要介绍了Java将word文件转成pdf文件的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • SpringCloud微服务中跨域配置的方法详解

    SpringCloud微服务中跨域配置的方法详解

    在使用SpringCloud实现微服务时,经常会碰到前端页面访问多个二级域名的情况,跨域是首先要解决的问题。解决这个问题,可以从两方面入手,一种方案是在微服务各自的业务模块中实现,即在SpringBoot层实现,另外一种方案就是在Gateway层实现
    2023-02-02
  • idea创建springboot项目,java版本只能选择17和21的解决方案

    idea创建springboot项目,java版本只能选择17和21的解决方案

    这篇文章主要介绍了idea创建springboot项目,java版本只能选择17和21的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • 一文详细springboot实现MySQL数据库的整合步骤

    一文详细springboot实现MySQL数据库的整合步骤

    Spring Boot可以很方便地与MySQL数据库进行整合,下面这篇文章主要给大家介绍了关于springboot实现MySQL数据库的整合步骤,文中通过图文以及代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • springMVC 用户登录权限验证实现过程解析

    springMVC 用户登录权限验证实现过程解析

    这篇文章主要介绍了springMVC 用户登录权限验证实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • SpringBoot中的404错误:原因、影响及解决策略

    SpringBoot中的404错误:原因、影响及解决策略

    本文详细介绍了SpringBoot中404错误的出现原因、影响以及处理策略,404错误常见于URL路径错误、控制器配置问题、静态资源配置错误、依赖缺失或版本不兼容、配置错误和服务器配置问题,解决方法包括检查URL路径、审查控制器配置、配置静态资源
    2025-02-02
  • 使用jxls自定义命令设置动态行高

    使用jxls自定义命令设置动态行高

    这篇文章主要介绍了使用jxls自定义命令设置动态行高,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java垃圾回收finalize()作用详解

    Java垃圾回收finalize()作用详解

    这篇文章主要为大家详细介绍了Java垃圾回收finalize()作用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-09-09
  • Java的Synchronized关键字学习指南(全面 & 详细)

    Java的Synchronized关键字学习指南(全面 & 详细)

    这篇文章主要给大家介绍了关于Java的Synchronized关键字的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03

最新评论