volatile 禁止指令重排

首先编译器执行指令的时候会存在指令重排的情况,以便于提高指令的执行速度。就像是考试一样,肯定是先把会的题做完再做难的题目。什么时候会发生重排,也就是两个指令之间不会存在依赖性,例如: a = 1; y = a+1。这两个语句就不会发生指令重排,因为y的值依赖a的值;但是如果是: a =1 ; y = 2 。这两个语句就会发生,因为不存在依赖。

在单线程的条件下,指令重排不会影响到最终的结果,也就是数据的一致性可以得到保证;但是再多线程的条件下,各种线程交替执行,两个线程间使用的变量能否保证一致性就不能得到保证。

案例一:

x,y=0

线程一

线程二
x=ay=b
b=1a=3

在上述条件下,如果正常的话,那么执行结束之后,x和y的值应该还是0;但是由于存在指令重排,那么线程一可以先执行b=1 =>x=a; 线程二可以先执行a=3 => y=b, 最终的结果就是 x =3, y=1。

案例二:

public class SortSeqDemo {
    int a = 0;
    boolean flag = false;
    
    public void method01() {
        a = 1;
        flag = true;
    }
    
    public void method02() {
        if (flag) {
            a = a+5;
            System.out.println(a);
        }
    }
}

在这个案例中, 如果执行method01() 方法的时候, a=1; flag = true; 这两个语句的执行顺序不能被保证,所以另一个线程执行method02()方法最终打印出来的a的值可能存在两种情况, a = 6 or a = 5。

而volatile就可以解决指令重排,它使用的是内存屏障进行解决的,所谓的内存屏障是一个cpu命令,它有两个作用保证特定的执行顺序,保证可见性,通过在volatile 指令前后增加内存屏障从而解决指令重排问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值