Volatile关键字问题总结

‼️该变量的所有更新操作对所有线程都是可见的

1. 作用:

1️⃣ 保证可见性,线程修改volatile变量后,其他线程能立即看到最新值。(可见性)

2️⃣ 防止指令重排,volatile变量的写入不会被重排序到它之前的代码。(有序性)

2. 如何保证可见性?

线程对volatile变量进行写操作时,JVM会在这个变量后插入一个写屏障指令,强制本地内存中的变量值刷新到主内存中。

线程对volatile变量进行读操作时,JVM会插入一个读屏障指令,换个指令会强制让本地内存中的变量值失效,重新从主内存中读取最新的值。

E.g. 线程A写入volatile变量,该变量被写入主内存中;线程B从本地内存中读取该变量,失效,要从主内存中读取该变量最新的值。

3. 如何保证有序性?

普通读
普通写
——————
StoreStore  禁止上面的普通写和下面的volatile写的重排
——————

volatile写

——————
StoreLoad  禁止下面的volatile读和volatile写的重排
——————

volatile读
——————
LoadLoad  禁止上面的volatile读和下面的普通读的重排
——————

——————
LoadStore  禁止下面的volatile读和下面的普通写的重排
——————

普通读
普通写

4. volatile在汇编语言层面是怎么实现的

在汇编语言层面,💡volatile 主要是通过在写操作后添加一个带有 lock 前缀的指令来实现的。

这个 lock 前缀有两个核心作用:

✨它充当了内存屏障,防止了指令重排序。

它会触发硬件的缓存一致性机制(如 MESI),强制将修改后的数据刷入主存,并让其他 CPU 缓存中的该数据失效,从而保证了可见性。

5. volatile和synchronized的区别?

volatile:该变量的所有更新操作对所有线程都是可见的。

synchronized:确保同一时刻只有一个线程能够执行该方法或代码块,实现互斥访问

6. volatile和synchronized的实现原理?

volatile 的实现:主要靠汇编层面的 lock 前缀指令。它充当了💡内存屏障,强制把修改后的值刷回主存并让其他缓存失效,从而解决可见性和有序性问题。

synchronized 的实现:synchronized 依赖 💡JVM 内部的 Monitor 对象来实现线程同步。使用的时候不用手动去 lock 和 unlock,JVM 会自动加锁和解锁。
synchronized 加锁代码块时,JVM 会通过 monitorenter 、 monitorexit 两个指令来实现同步:
前者表示线程正在尝试获取 lock 对象的 Monitor; 后者表示线程执行完了同步代码块,正在释放锁。
使用 javap -c -s -v -l SynchronizedDemo.class 反编译 synchronized 代码块时,就能看到这两个指令。 synchronized 修饰普通方法时,JVM 会通过 ACC_SYNCHRONIZED 标记符来实现同步。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

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