校招刷题群
高效刷题 迎战校招
校招精选试题
近年面笔经面经群内分享
Java刷题群 前端刷题群 产品运营群
首页 > java语言 > final/static/volatile(后序会删除)
题目

说一下volatile这个关键字的作用?

解答

JMM 为 volatile 定义了一些特殊访问规则,当变量被定义为 volatile 后具备两种特性:

保证变量对所有线程可见

当一条线程修改了变量值,新值对于其他线程来说是立即可以得知的。
volatile 变量在各个线程的工作内存中不存在一致性问题,但 Java 的运算操作符并非原子操作,导致 volatile 变量运算在并发下仍不安全。

禁止指令重排序优化

使用 volatile 变量进行写操作,汇编指令带有 lock 前缀,相当于一个内存屏障,后面的指令不能重排到内存屏障之前。

使用 lock 前缀引发两件事:
① 将当前处理器缓存行的数据写回系统内存。
②使其他处理器的缓存无效。相当于对缓存变量做了一次 store 和 write 操作,让 volatile 变量的修改对其他处理器立即可见。

静态变量 i 执行多线程 i++ 的不安全问题

自增语句由 4 条字节码指令构成的,依次为 getstatic、iconst_1、iadd、putstatic,当 getstatic 把 i 的值取到操作栈顶时,volatile 保证了 i 值在此刻正确,但在执行 iconst_1、iadd 时,其他线程可能已经改变了 i 值,操作栈顶的值就变成了过期数据,
所以 putstatic 执行后就可能把较小的 i 值同步回了主内存。

适用场景

① 运算结果并不依赖变量的当前值。② 一写多读,只有单一的线程修改变量值。

内存语义

写一个 volatile 变量时,把该线程工作内存中的值刷新到主内存。

读一个 volatile 变量时,把该线程工作内存值置为无效,从主内存读取。

指令重排序特点

第二个操作是 volatile 写,不管第一个操作是什么都不能重排序,确保写之前的操作不会被重排序到写之后。

第一个操作是 volatile 读,不管第二个操作是什么都不能重排序,确保读之后的操作不会被重排序到读之前。

第一个操作是 volatile 写,第二个操作是 volatile 读不能重排序。

JSR-133 增强 volatile 语义的原因

在旧的内存模型中,虽然不允许 volatile 变量间重排序,但允许 volatile 变量与普通变量重排序,可能导致内存不可见问题。
JSR-133 严格限制编译器和处理器对 volatile 变量与普通变量的重排序,确保 volatile 的写-读和锁的释放-获取具有相同的内存语义。

C 3条回复 评论
欢乐马

涨知识了

发表于 2023-06-15 21:00:00
0 0
知乎

我想问一下前端面试的时候可以自选语言嘛?平常刷题都是用的java语言…

发表于 2022-07-23 22:00:00
0 0
青梅煮酒

面试官逮着我问内存溢出和内存泄露,k8s,测试前置,jekins集群的问题

发表于 2021-09-09 19:35:00
0 0