栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java Volatile不能指令重排原因

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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内屏障的作用,优势是使用后能够提升整体线程的安全性问题。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/15200.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号