volatile关键字原理的使用介绍和底层原理解析和使用实例

1. volatile 关键字的作用

volatile 关键字的主要作用是保证可见性和有序性,禁止编译器优化。

  • 保证可见性:当一个变量被声明为 volatile 之后,每次读取这个变量的值都会从主内存中读取,而不是从缓存中读取,这就保证了不同线程对这个变量操作的可见性。
  • 有序性:volatile 关键字保证了不同线程对一个 volatile 变量的读写操作的有序性。
  • 禁止编译器优化:编译器会对代码进行各种优化来提高性能,但是这些优化也可能让同步代码失效。volatile 关键字告诉编译器不要对这段代码做优化,从而避免一些不正确的优化。

2. volatile 的底层原理

volatile 关键字底层原理依赖于内存屏障和缓存一致性协议。

  • 内存屏障:内存屏障会强制让读和写操作都访问主内存,从而实现可见性。volatile 写操作后会加入写屏障,volatile 读操作前会加入读屏障。
  • 缓存一致性协议:每个处理器都有自己的高速缓存,当某个处理器修改了共享变量,需要缓存一致性协议来保证其他处理器也看到修改后的值。缓存一致性协议会在读操作后和写操作前加入缓存刷新操作,保证其他处理器的缓存是最新值。

3. volatile 的使用案例

volatile 关键字常用在 DCL(Double Check Lock)单例模式中:

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
复制代码

这里使用 volatile 是为了防止指令重排序,保证 instance 初始化后其他线程可以看到。

volatile 也常用在Interruptible线程中,实现线程的中断功能:

public class InterruptibleThread extends Thread {
    private volatile boolean interrupted = false;

    public void interrupt() {
        interrupted = true;
    }

    @Override
    public void run() {
        while (!interrupted) {
            // do something
        }
    }
}
复制代码

这里 volatile 可以保证 interrupted 的可见性,使线程立即响应中断调用。

4. volatile 的原子性问题

volatile 关键字只能保证可见性和有序性,不能保证原子性。

对一个 volatile 变量的读写操作并不是原子的,而是可以分为读、改、写三个操作:

  • 读: 读取 volatile 变量的值
  • 改:对值进行修改
  • 写:将修改后的值写入 volatile 变量

这三个操作并不是一个原子操作,在多线程环境下可能导致数据竞争问题:

public class VolatileNoAtomicDemo {
    private volatile int counter = 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值