java Volatile不能指令重排原因

java Volatile不能指令重排原因,第1张

java Volatile不能指令重排原因

代码的顺序改变后,虽然变量值没有变化,但是对于线程的使用时容易发生不安全的问题。这里也是我们用Volatile时一再说明不能用于重排的原因。下面我们就为大家分析重排导致线程不安全的实例,以及Volatile为了避免这种不安全的情况的发生,所采取的内存屏障的方法。

1.Volatile重排导致线程不安全

对于有些代码进行重排序之后,虽然对变量的值没有造成影响,但有可能会出现线程安全问题的。具体请看下面的代码

public class NoVisibility{
    private static boolean ready;
    private static int number;
 
    private static class Reader extends Thread{
        public void run(){
        while(!ready){
            Thread.yield();
        }
        System.out.println(number);
 
    }
}
    public static void main(String[] args){
        new Reader().start();
        number = 42;
        ready = true;
    }
}

这段代码最终打印的一定是42吗?如果没有重排序的话,打印的确实会是42,但如果number = 42和ready = true被进行了重排序,颠倒了顺序,那么就有可能打印出0了,而不是42。(因为number的初始值会是0)。

因此,重排序是有可能导致线程安全问题的。

2.Volatile内存屏障防止重排

Volatile实现禁止指令重排优化,从而避免了多线程环境下程序出现乱序执行的现象。

首先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

(1)保证特定 *** 作的顺序

(2)保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

由于编译器和处理器都能执行指令重排的优化,如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说 通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。 内存屏障另外一个作用是刷新出各种CPU的缓存数,因此任何CPU上的线程都能读取到这些数据的最新版本。

在Volatile的写和读的时候,加入屏障,防止出现指令重排,线程安全获得保证。

以上就是java Volatile不能指令重排原因,这也是发挥Volatile内屏障的作用,优势是使用后能够提升整体线程的安全性问题。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/3017625.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-28
下一篇 2022-09-28

发表评论

登录后才能评论

评论列表(0条)

保存