volatile 关键字

Scroll Down

volatile 关键字

volatile 是一个类型修饰符,它是被设计用来修饰被不同线程访问和修改的变量。在使用 volatile 修饰成员变量后,所有线程在任何时间所看到变量的值都是相同的。此外,使用 volatile 会影响到编译器对代码的优化,因此会降低程序的执行效率。

volatile 可以保证并发三大安全性的可见性原则

  • 每次访问变量时,总是获取主内存的最新值
  • 每次修改变量后,立刻写回到主内存中

volatile 的可见性保证不仅对 volatile 修饰的变量生效

  • 线程A去写一个 volatile 修饰的变量,线程B随后也要去读这个变量,那么在线程A中所有写变量操作在 volatile 变量之前的对A可见的变量也会对B可见
  • 如果线程A去读一个volatile变量,则所有对线程A可见的变量,在线程A读取这个volatile变量时,会从主存中重新读一次

例子:

public class MyClass {
    private int years;
    private int months
    private volatile int days;


    public void update(int years, int months, int days){
        this.years  = years;
        this.months = months;
        this.days   = days;
    }
}
// 当days变量被写入时,years和months因为对当前线程可见,也会被写入到主存中

public class MyClass {
    private int years;
    private int months
    private volatile int days;

    public int totalDays() {
        int total = this.days;
        total += months * 30;
        total += years * 365;
        return total;
    }

    public void update(int years, int months, int days){
        this.years  = years;
        this.months = months;
        this.days   = days;
    }
}
// totalDays()方法执行时,第一步读取days的值,因为days时volatile变量,所以所有对当前线程可见的变量都会从主存中重新读一次

volatile 的 Happens-Before 原则

  • 对其它变量的读和写操作不能被重排序到对一个volatile变量的写操作之后。
  • 对其他变量的读和写操作不能被重排序到对一个volatile变量的读操作之前。