技术文章 > java >  java基础 > 正文

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

免费视频教程
本文原创发布python学习网,转载请注明出处,感谢您的尊重!
相关文章
 java线程组的批量管理
 同步在java线程的理解
 线程同步在java中的操作
 java volatile的特性是什么
相关视频章节
 网络爬虫
 云端部署Web应用程序视频
 Web应用框架Flask和文件模板
 Web应用程序开发概述
 继承和多态
作者信息
推荐视频
视频教程分类