概述

听说当两条指令互相不依赖的时候,在cpu或者jvm那儿可能会为了提高性能而进行指令重排。

数据依赖

比如下面两条代码就没有数据依赖:

int  a = 5;

int  b= 2;

这两条指令先后顺序并不影响程序运行逻辑,重排也是是没有问题的。

多线程

但是,听说在多线程的时候就会出现问题,因为单个线程有依赖可以检测出来。

多个线程操作同一个对象的时候,因为每个线程都有自己的工作区,主存与工作内存交互不及时,就会导致数据出问题。

来个例子:

代码分析:


/**
     * 理论上来说:
     * 1.线程1先执行完,线程2开始执行
     *          a=1;
     *          flag=true;
     *          if (flag) {
     *                     a = a + 5;
     *                     System.out.println("reValue:" + a);
     *                 }
     *  运行结果是:输出reValue:6
     *
     *  2.线程1先执行一半,线程2执行
     *          a=1;
     *          if (flag) {
     *             a = a + 5;
     *             System.out.println("reValue:" + a);
     *          }
     *          flag=true;
     *  运行结果:无。
     *
     * 3.线程2先执行,线程1开始执行
     *          if (flag) {
     *                     a = a + 5;
     *                     System.out.println("reValue:" + a);
     *                 }
     *          a=1;
     *          flag=true;
     *  运行结果是:无。
     *
     * 如果在线程1中发生指令重排!!!!!
     * 就会出现:
     * 线程1先执行一半,线程2执行
     *          flag=true;
     *          if (flag) {
     *             a = a + 5;
     *             System.out.println("reValue:" + a);
     *          }
     *          a=1;
     * 运行结果:控制台输出reValue:a
     */

点击查看

运行结果:

 

实不相瞒,秉持着实事求是的原则,不经历过的我不信。

我i5第十二代处理器,运行了一晚上,只出了这一次指令重排。它真的,我哭死。

还好运行出来一次,我勉强信了。

总结

它如何产生:

就是因为每个线程都有自己的工作内存,而工作内存与主内存交互不够及时呗。

 

 

它如何解决:

当你觉得某个变量会因为指令重排而导致线程不安全,那么对其使用volatile的声明,它使得变量及时地在主存中更新 :

1、对volatile变量的写会立即刷新到主存
2、对volatile变量的读会读主存中的新值

原文地址:http://www.cnblogs.com/lurenjia-bky/p/16886709.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性