深入理解关键字volatile

本文深入探讨了Java中的volatile关键字,解释了它如何确保可见性和有序性,但无法保证原子性。通过内存模型和内存屏障,volatile确保了多线程环境下共享变量的即时更新和禁止指令重排序,但在复合操作如i++中,仍然无法确保原子性。文章还列举了volatile在状态标志位、双重检查DLC和读写锁等应用场景。
摘要由CSDN通过智能技术生成

volatile 关键字的作用是什么?

相比于 synchronized 关键字(重量级锁)对性能影响较大,Java提供了一种较为轻量级的可见性和有序性问题的解决方案,那就是使用 volatile 关键字。由于使用 volatile 不会引起上下文的切换和调度,所以 volatile 对性能的影响较小,开销较低。

从并发三要素的角度看,volatile 可以保证其修饰的变量的可见性有序性,无法保证原子性(不能保证完全的原子性,只能保证单次读/写操作具有原子性,即无法保证复合操作的原子性)。

下面将从并发三要素的角度介绍 volatile 如何做到可见和有序的。


1. volatile 如何实现可见性?

什么是可见性?

可见性指当多个线程同时访问共享变量时,一个线程对共享变量的修改,其他线程可以立即看到(即任意线程对共享变量操作时,变量一旦改变所有线程立即可以看到)。

1.1 可见性例子

/**
 * volatile 可见性例子
 * @author 单程车票
 */
public class VisibilityDemo {

    // 构造共享变量
    public static boolean flag = true;
//    public static volatile boolean flag = true;   // 如果使用volatile修饰则可以终止循环

    public static void main(String[] args) {
        // 线程1更改flag
        new Thread(() -> {
            // 睡眠3秒确保线程2启动
            try { TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {e.printStackTrace();}
            // 修改共享变量
            flag = false;
            System.out.println("修改成功,当前flag为true");
        }, "one").start();

        // 线程2获取更新后的flag终止循环
        new Thread(() -> {
            while (flag) {

            }
            System.out.println("获取到修改后的flag,终止循环");
        }, "two").start();
    }
}
  • 不使用 volatile 修饰 flag 变量时,运行程序会进入死循环,也就是说线程1对 flag 的修改并没有被线程2读到,也就是说这里的flag并不具备可见性。
  • 使用 volatile 修饰 flag 变量时,运行程序会终止循环,打印提示语句,说明线程2读到了线程1修改后的数据,也就是说被 volatile 修饰的变量具备可见性。

1.2 volatile 如何保证可见性?

被 volatile 修饰的共享变量 flag 被一个线程修改后,JMM(Java内存模型)会把该线程的CPU内存中的共享变量 flag 立即强制刷新回主存中,并且让其他线程的CPU内存中的共享变量 flag 缓存失效,这样当其他线程需要访问该共享变量 flag 时,就会从主存获取最新的数据。

所以通过 volatile 修饰的变量可以保证可见性。

两点疑问及解答:

  1. 为什么会有CPU内存? 为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1/L2/其他)后再进行操作,但是操作完后的数据不知道何时才会写回主存。所以如果是普通变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值