小蔡学Java

谈谈对 volatile 的理解

2023-12-12 11:36 1204 0 JVM / JUC JUC

前言

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: ① 保证线程间的可见性禁止进行指令重排序

保证线程间的可见性

用 volatile 修饰共享变量,能够 防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见

运行结果

明明已经把stop改成了true,但是第三个线程依然没有打印stopped... c:253562931,说明一直在死循环,即 其他线程没有感知到stop的变化

问题分析:主要是因为在JVM虚拟机中有一个JIT(即时编译器)给代码做了优化。

解决方案一:在程序运行的时候加入vm参数-Xint表示 禁用即时编译器 ,不推荐,得不偿失(其他程序还要使用)

解决方案二:在修饰stop变量的时候加上volatile,当前告诉 jit,不要对 volatile 修饰的变量做优化

volatile禁止指令重排序

用 volatile 修饰共享变量会在读、写共享变量时加入不同的屏障,阻止 其他读写操作越过屏障,从而达到阻止重排序的效果

注解@Actor保证方法内的代码在同一个线程下执行

运行发现还是有情况四的存在

在变量上添加volatile,禁止指令重排序,则可以解决问题

volatile使用技巧:

  • 写变量让volatile修饰的变量的在代码最后位置
  • 读变量让volatile修饰的变量的在代码最开始位置

总结Voliate

①保证线程间的可见性 用 volatile 修饰共享变量,能够防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见 ② 禁止进行指令重排序 指令重排:用 volatile 修饰共享变量会在读、写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到阻止重排序的效果

评论( 0 )

  • 博主 Mr Cai
  • 坐标 河南 信阳
  • 标签 Java、SpringBoot、消息中间件、Web、Code爱好者

文章目录