分享

volatile关键字的理解

 行者花雕 2021-05-30

  首先volatile只能修饰实例变量或者类变量,不能修饰方法、局部变量、方法参数等。并发的三个至关重要的特性,原子性可见性、有序性,volatile只能保证前面的两个特性,所以使用volatile关键字要在合适的业务场景。

  一、volitile的可见性

  多线程的可见性,简单来说是指多个线程共享的变量修改以后,各个线程都能看到变量已经修改了,并且从主内存中拷贝变量改变后的值。

        

public class TestVisibility {
    private static boolean stopFlag;

    public static void main(String[] args)throws InterruptedException{

        Thread loop = new Thread(()->{
            int i=0;
            while(!stopFlag){
                i++;
            }
            System.out.println("Thread is stopped and evaluated result is:"+i);
        });
        loop.start();
        TimeUnit.SECONDS.sleep(1);
        stopFlag = true;
    }
}

 

  上面的TestVisibility的测试类,预计期望1秒后程序会停止并打印出计算结果,但运行结果是它会一直运行没有停止。

        变量stopFlag是基本数据类型所以线程操作是原子的,单个原子操作是线程安全的,但是只能保证原子性,对其他线程是不可见的,在主线程sleep一段时间后 stopFlag 的修改子线程loop没有感知到,循环会一直继续下去。

        要使loop线程在sleep后正常退出,可以stopFlag前加上volatile关键字就可以了,因为volatile是可以保证可见性的。 

  二、有序性

  有序性:是指按照代码的先后的执行程序。但是由于Java编译器的优化,代码的执行顺序不一定是你编写后代码的顺序。

       

int x=0;
int y=0;
x++;
y=20

  上面的代码执行可能是按照从上至下编写的顺序执行的,但在jvm执行的时候不一定是这样的顺序,有可能 y=20 在x++的前面执行,这就是指令的重排序。

   volatile可以保证有序性。volatile对修饰的变量前后无依赖关系的指令可以随便怎么排序:

1 int x=0;
2 int y=0;
3 volatile z=20;
4 x++;
5 y=20

上面第3行的前后的逻辑不管怎么排列,只要到第3行执行的时候x=0 y=0就可以。对变量z多个线程进行操作,volatile的有序性强制限制修改变量的线程要在读的线程之前。

  

 

  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多