首页 > 试题广场 >

说一说你对volatile关键字的理解

[问答题]

说一说你对volatile关键字的理解

推荐

得分点

​ 可见性、内存语义

参考答案

标准回答

​ volatile用于保证内存的可见性,可以将其看做是轻量级的锁,它具有如下的内存语义:

  • 写内存语义:当写一个volatile变量时,JMM会把该线程本地内存中的共享变量的值刷新到主内存中。
  • 读内存语义:当读一个volatile变量时,JMM会把该线程本地内存置为无效,使其从主内存中读取共享变量。

​ 其中,JMM是指Java内存模型,而本地内存只是JMM的一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。在本文中,大家可以将其简单理解为缓存。

​ volatile只能保证单个变量读写的原子性,而锁则可以保证对整个临界区的代码执行具有原子性。所以,在功能上锁比volatile更强大,在可伸缩性和性能上volatile更优优势。

加分回答

​ volatile的底层是采用内存屏障来实现的,就是在编译器生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。内存屏障就是一段与平台相关的代码,Java中的内存屏障代码都在Unsafe类中定义,共包含三个方法:LoadFence()、storeFence()、fullFence()。

延伸阅读

​ 可见性是指一个线程对共享变量的修改,另外一个线程能够立刻看到。可见性问题是由CPU缓存导致的,每核CPU均有各自的缓存,这些缓存均要与内存进行同步。例如,线程A要修改内存中变量X,它需要先将变量X加载到本地缓存,修改缓存后再将缓存数据刷回内存中。在线程A修改本地缓存中变量X时,线程B可能也需要读/写内存中的变量X,为了让线程A的修改对线程B感知到,就可以在变量X前加上volatile来解决。


图片说明
​ 在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序不会影响单线程的执行结果,但是在并发的情况下,可能会出现诡异的BUG。例如,instance = new Singleton(); 这行代码在执行时,会产生3条字节码指令,而这三条指令的顺序就可能会被编译器重排。CPU在执行指令时会保证每条指令的原子性,但是不会保证这三条指令是原子的。所以在三条指令执行期间可能会出现CPU轮换的情况,BUG就可能在这种情况下产生了。


图片说明

编辑于 2021-09-15 10:36:19 回复(0)
1.volitale 保证可见性 和  防止重排序
2. 增加了volitale的时候,
    2.1 写的时候, 会把当前线程的共享变量的值刷新的主内存中
    2.2 读的时候,当前线程的共享变量的值无效,只能从主内存读取
3. 它保证单个变量的读/写原子性,比synchronize 轻量级
4. 通过内存屏蔽的方式防止重排序
发表于 2022-02-18 17:58:02 回复(3)

volatile用于保证内存的可见性,可以将其看做是轻量级的锁,它具有如下的内存语义:

  • 写内存语义:当写一个volatile变量时,JMM会把该线程本地内存中的共享变量的值刷新到主内存中。
  • 读内存语义:当读一个volatile变量时,JMM会把该线程本地内存置为无效,使其从主内存中读取共享变量。

其中,JMM是指Java内存模型,而本地内存只是JMM的一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。在本文中,大家可以将其简单理解为缓存。

volatile只能保证单个变量读写的原子性,而锁则可以保证对整个临界区的代码执行具有原子性。所以,在功能上锁比volatile更强大,在可伸缩性和性能上volatile更优优势。

加分回答

volatile的底层是采用内存屏障来实现的,就是在编译器生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。内存屏障就是一段与平台相关的代码,Java中的内存屏障代码都在Unsafe类中定义,共包含三个方法:LoadFence()、storeFence()、fullFence()。


发表于 2021-12-08 09:58:13 回复(0)
链接:https://www.nowcoder.com/questionTerminal/d05c04f81dae4936807b8d6c6cabecc0
来源:牛客网

标准回答

volatile用于保证内存的可见性,可以将其看做是轻量级的锁,它具有如下的内存语义:

  • 写内存语义:当写一个volatile变量时,JMM会把该线程本地内存中的共享变量的值刷新到主内存中。
  • 读内存语义:当读一个volatile变量时,JMM会把该线程本地内存置为无效,使其从主内存中读取共享变量。

其中,JMM是指Java内存模型,而本地内存只是JMM的一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。在本文中,大家可以将其简单理解为缓存。

volatile只能保证单个变量读写的原子性,而锁则可以保证对整个临界区的代码执行具有原子性。所以,在功能上锁比volatile更强大,在可伸缩性和性能上volatile更优优势。

加分回答

volatile的底层是采用内存屏障来实现的,就是在编译器生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。内存屏障就是一段与平台相关的代码,Java中的内存屏障代码都在Unsafe类中定义,共包含三个方法:LoadFence()、storeFence()、fullFence()。

发表于 2021-11-22 11:17:17 回复(0)
更透彻了
发表于 2021-11-17 21:38:51 回复(0)