CPU为了提高执行效率,会在一条指令执行的过程中(比如去内存读数据,读数据的过程相较于CPU的执行速度慢100倍以上,cpu处于等待状态),这个时候cpu会分析接下来的指令是否正在执行的指令相关联,如果不相关,那么cpu就会去执行接下来的指令,这就是造成cpu执行指令乱序问题的原因。

怎么证明cpu乱序执行这件事呢

借用一位大神的小程序来验证这个问题

我们通过反证法来验证:如果cpu执行指令未重排,可以预见,上面这个小程序x, y最终结果只存在三种组合(0,1)(1,0)(1,1);判断条件中永远不可能输出

接下来我们来验证该结果

从输出结果上来看执行了568+万次才出现了(0,0)的组合,每次执行什么时候产生这种结果都是未知的。原因是 a = 1;在cpu执行的时候不是一条指令,而是由多条指令。所以想要x = b 在a = 1之前执行的概率还是比较低的

我们验证了确实可能存在乱序执行的问题。

我们来看一个实际问题:

  一个简单的单例模式

这个过程会有什么问题存在呢,跟指令重排又有什么关系呢

1、在new一个对象的时候会经历以下几个步骤

  第一步new的过程简单来说为对象分配内存空间,第二步dup很复杂这里暂时不在多说,第三步invokespecial初始化对象,第四步astore_1把引用指向变量(比如上面的t)。

在第三步和第四步之间没有任何依赖关系,可能就会发生指令的重排,也就是说对象还没有初始化的时候已经把引用指向了t。

这时候会有什么问题呢?

  如果有另外一个线程执行到外层if判断时,发现的对象已经不为空,它就执行拿来使用(记住这个时候对象还没有初始化,所有变量都还是初始值状态),如果有个成员变量设置的m = 100;完蛋这个时候该线程拿到的对象里的m还是初始值为0,如果那这个值去参与计算就会有大问题了。

该如何解决呢?大神们已经给出答案了

就是在t变量上加上volatile修饰,它有一个作用就是禁止指令重排。

网络上大神还是多,多看看一些技术文档,我们都可以站在巨人的肩膀上前行。

CPU乱序执行问题的更多相关文章

  1. cpu乱序执行

    http://blog.163.com/zhaojie_ding/blog/static/1729728952007925111324379/?suggestedreading 处理器的乱序和并发执行 ...

  2. cpu 乱序执行与问题【转】

    转自:https://blog.csdn.net/lizhihaoweiwei/article/details/50562732 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议 ...

  3. CPU乱序执行基础 —— Tomasulo算法及执行过程

    朋友们可以关注下我的公众号,获得最及时的更新: IBM 360/91浮点单元最先实现Tomasulo算法从而允许乱序执行.360体系只有4个双精度浮点寄存器,限制了编译器调度的有效性.而且,IBM 3 ...

  4. C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI

    目录 1. 前言2 2. 结论2 3. volatile应用场景3 4. 内存屏障(Memory Barrier)4 5. setjmp和longjmp4 1) 结果1(非优化编译:g++ -g -o ...

  5. CPU Meltdown和Spectre漏洞分析

    一.背景: 1月4日,国外爆出了整个一代处理器都存在的灾难性漏洞:Meltdown和Spectre. 几乎影响了全球20年内所有cpu处理器:这两个漏洞可以使攻击者通过利用并行运行进程的方式来破坏处理 ...

  6. 现代cpu的合并写技术对程序的影响

    对于现代cpu而言,性能瓶颈则是对于内存的访问.cpu的速度往往都比主存的高至少两个数量级.因此cpu都引入了L1_cache与L2_cache,更加高端的cpu还加入了L3_cache.很显然,这个 ...

  7. 浅谈原子操作、volatile、CPU执行顺序

    浅谈原子操作.volatile.CPU执行顺序 在计算机发展的鸿蒙年代,程序都是顺序执行,编译器也只是简单地翻译指令,随着硬件和软件的飞速增长,原来的工具和硬件渐渐地力不从心,也逐渐涌现出各路大神在原 ...

  8. C++11 并发指南七(C++11 内存模型一:介绍)

    第六章主要介绍了 C++11 中的原子类型及其相关的API,原子类型的大多数 API 都需要程序员提供一个 std::memory_order(可译为内存序,访存顺序) 的枚举类型值作为参数,比如:a ...

  9. 内存屏障(Memory barrier)-- 转发

    本文例子均在 Linux(g++)下验证通过,CPU 为 X86-64 处理器架构.所有罗列的 Linux 内核代码也均在(或只在)X86-64 下有效. 本文首先通过范例(以及内核代码)来解释 Me ...

随机推荐

  1. pandas常用操作详解(复制别人的)——数据透视表操作:pivot_table()

    原文链接:https://www.cnblogs.com/Yanjy-OnlyOne/p/11195621.html 一文看懂pandas的透视表pivot_table 一.概述 1.1 什么是透视表 ...

  2. 02 基础 卸载JDK 安装JDK Java程序运行机制

    基础 JDK:Java Development Kit(Java开发者工具 包含JRE和JVM) JRE:Java Runtime Environment(java运行时环境,包含JVM) JVM:J ...

  3. NET 中反射的用法

    1.   反射的学习 A.反射的定义 B.反射举例 namespace Com.Meteor.Interface { public interface IHelper { void Query(); ...

  4. Docker——部署常用镜像

    部署nginx:暴露端口 #下载nginx docker pull nginx #运行nginx docker run -d --name nginx2 -p 8081:80 nginx -d #后台 ...

  5. YCCMS 3.3 CSRF漏洞--代码执行

    一. 启动环境 1.双击运行桌面phpstudy.exe软件 2.点击启动按钮,启动服务器环境 二.代码审计 1.双击启动桌面Seay源代码审计系统软件 2.点击新建项目按钮,弹出对画框中选择(C:\ ...

  6. windows server 2019 域控批量新增不用,只看这一篇就够了,别的不用看

    windows server 2019 域控批量新增不用,只看这一篇就够了,别的不用看 1. 新建excel表格 A B C D E 姓 名 全名 登录名 密码 李 四 李四 李四 test123!@ ...

  7. Tomcat启动时shell窗口乱码解决方法

    tomcat/conf/目录下,修改logging.properties java.util.logging.ConsoleHandler.encoding = utf-8 更改为 java.util ...

  8. SpringMVC怎么样设定重定向和转发的?

    (1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4" (2)重定向:在返回值前面加"red ...

  9. BeanFactory和ApplicationContext有什么区别?

    BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器.其中ApplicationContext是BeanFactory的子接口. (1 ...

  10. docker打包镜像,测试部署

    docker基本入门以后,(docker基本入门https://www.cnblogs.com/yangyangming/p/11470926.html)可以试试打包docker镜像与dockerfi ...