无论程序语言如何千变万化,他们都深深地根植于目前的计算机体系结构。

左图是intel CPU的三级高速缓存设计,由于高速缓存对程序员基本不可见,因此可以抽象为右图。

缓存的设计

首先还是先谈谈左图。

L1-cache分为两部分,i-cache存储指令(只读),d-cache存储数据(可读可写)

CPU只能和寄存器以及L1-cache进行直接交互,数据不能隔层传递,只能一层一层往上读,一层一层往下写

访问L1需要至少4个时钟周期,L2需要至少10个,L3需要至少30个。即便是速度最快的L1,也低于运算单元的执行速度,何况存在缓存未命中的情况,因此在L1和运算单元之间加上了Writebuffer和Readbuffer(合称Memory Ordering Buffer,MOB),数据准备好的时候再完成相关指令,这就是CPU指令乱序——顺序执行乱序完成。乱序完成的结果放入到Writebuffer中,按照原有的执行顺序,刷到缓存中

缓存由多个缓存行组成。每个缓存行结构如图所示(以64位机器为例)

CPU读取缓存的时候找到对应的缓存行,如果前面的有效位为零,就从下一级缓存加载到这一级缓存

相关的问题

明白缓存的设计之后,再看右图来分析其中的问题

缓存导致的内存可见性:已知线程A运行在core 0上,线程B运行在core 1上,两者都对同一个内存地址进行读取,这个内存地址的内容会被加载到cache,然后CPU读取,这时候线程A对内容进行了修改,但是线程B却可能一直从本核心的cache读取,无法感知到该地址的内容已被修改。

多核导致的自增操作原子性:自增操作分为三步:从内存读取变量到寄存器;寄存器中的值加1;写回到内存。已知线程A运行在core 0上,线程B运行在core 1上,两者都对变量执行加一操作。A执行完一二两步时,B执行完第一步,A将加一后的值写入到内存,B执行完二三两步也将加一后的值写入到内存,结果变量只加了一,而不是加二

MOB导致的cache可见性:a=1.0; a=a/2; a=a-1.0;按照正常的逻辑,a最后的结果为-0.5;但是因为除法的执行时钟周期大于减法,第三句执行时,a/2的结果存放在writebuffer中还没写入到缓存,a-1.0中a的值已经从缓存中加载到readbuffer,也就是a-1.0=1.0-1.0=0 (高级语言不会出现这个问题,因为编译器已经做了处理,前面的伪代码仅表示逻辑)

相关的实现

为了解决这些问题,CPU提供了一些指令,其中比如lock和cmpxchg。

lock 汇编前缀,在Intel奔腾系列之前,这个指令前缀能够锁定总线,禁止其他CPU核心操作内存,执行完后边的指令后释放总线,在这个过程中其他CPU核心会监听总线,发现某个内存地址内容被修改,就会将本核心下的对应cache行有效位置0。因为锁总线会禁止所有内存操作,降低效率,因此在奔腾之后,这个指令前缀不锁总线而是锁定相关的cache行,对某个地址修改后直接让相关cache失效。这样解决了问题一

cmpxchg 将寄存器a中的值与内存中比较如果一样,将寄存器c中的值和内存中的值交换,如果不一样就设置异常位并将内存中的值读取到寄存器a。代入到问题二,从内存读取值到寄存器a,加一后保存到寄存器c,然后执行cmpxchg,执行完后如果有异常,就重新加一,再尝试写回,直到成功。这样解决了问题二

cmpxchg和lock 在执行完以后会将writebuffer刷到cache并清空readbuffer,这样解决了问题三。另外X86_64引入了内存屏障指令 lfence、sfence、mfence。lfence前面的读取操作完成,也就是readbuffer中的内容全部被cpu读取后,才能执行lfence之后的读取操作;sfence前面的写入操作完成,也就是writebuffer全部刷到缓存中,才能执行sfence之后的写入操作;mfence之前的读写操作全部完成,才能进行mfence之后的操作。

java硬件编程_关于JAVA并发编程你需要知道的——硬件篇相关推荐

  1. java内存屏障_内存屏障 | 并发编程网 – ifeve.com

    本文我将和大家讨论并发编程中最基础的一项技术:内存屏障或内存栅栏,也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术. CPU使用了很多优化技术来实现一个目标:CPU执行单元的速度要远 ...

  2. java对象头_我的并发编程(二):java对象头以及synchronized升级过程

    一.概述 研究java对象头的目的是详细分析Java的synchronized锁的升级过程,因为synchronized在锁升级的时候,就是依赖对象头的信息来决定的.本博文针对64位的操作系统来对Ja ...

  3. 并发编程-初级之认识并发编程

    并发编程-初级之认识并发编程 1.并发领域可以处理的问题 分工: 同步:分好工之后,就可以具体执行.任务之间是有依赖的,一个任务结束之后将去去通知后续的任务.java里面 Executor.Fork/ ...

  4. java 线程 并发_多线程高并发编程总结

    多线程 第一章 一.终止线程的三种方法: 1.使用退出标志,是县城正常退出,也就是当run方法完成后线程终止. 2.stop不推荐 3.使用interrupt(打了一个停止标记,并不是真的停止线程). ...

  5. java的尝试性问题_Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和有序性的问题,那么还有一个原子性问题咱们还没解决.在第一篇文章01并发编程的Bug源头当中,讲到了把一个或者多 ...

  6. Java 面试知识点解析(二)——高并发编程篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  7. java io复用_学习Java编程-IO复用

    原标题:学习Java编程-IO复用 对于服务器的并发处理能力,我们需要的是:每一毫秒服务器都能及时处理这一毫秒内收到的数百个不同TCP连接上的报文,与此同时,可能服务器上还有数以十万计的最近几秒没有收 ...

  8. java并发编程代码示例_java并发编程之同步器代码示例

    java并发编程之同步器代码示例 发布时间:2020-09-08 16:53:41 来源:脚本之家 阅读:58 作者:Blessing_H 同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作 ...

  9. java多线程编程_《java多线程编程实战指南》读书笔记 -- 基本概念

    展开 并发:多个线程操作相同资源,保证线程安全,合理使用资源 高并发:服务能同时处理多个请求,提高程序性能 测试上下文切换工具 Lmbench3 测量上下文切换时长 vmstat 测量上下文切换次数 ...

  10. java并发编程的艺术和并发编程这一篇就够了

    java并发编程的艺术(精华提炼) 通常我们在使用编发编程时,主要目的是为了程序能够更快的处理,但是并不是说更多的线程就一定能够让程序变得足够快,有时候太多的线程反而消耗了更多的资源,反而让程序执行得 ...

最新文章

  1. HTTP.sys 远程执行代码验证工具
  2. C语言经典例83-求0—7所能组成的奇数个数
  3. oracle没有groupby,oraclegroupby之后还可以groupby么
  4. python apache配置_Apache运行Python的配置
  5. java静态方法和非静态方法的区别_史上最全阿里 Java 面试题总结
  6. 电能储存系统行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. php抽奖简单源码,php转盘抽奖 完整例子源码(含模拟数据)
  8. IDEA如何快速切换项目(快捷键切换)
  9. 护眼软件Linux,四个 Linux 下的“护眼”软件解析
  10. 说说那些好用的图片调色软件
  11. Elastic 7.9 版本发布,提供免费的 Workplace Search 和终端安全功能
  12. maven dependency problem 问题
  13. 大数据零基础学习并不难,从0到1你需要的不仅仅是努力!
  14. python的re模块替换文件字符串_Python 正则处理_re模块
  15. 20 - Slider组件案例 相亲APP
  16. 优酷视频在网站里播放
  17. linux离线安装redmine_举个栗子!Tableau 技巧(97):离线安装 Linux 版 Tableau Server...
  18. ASP.NET Core Redis
  19. 开源中文古风排版样式,简约美观,超级好用!
  20. 逸管家:共享经济时代,逸管家引领中小企业走向辉煌

热门文章

  1. 改logback logstash-logback-encoder 框架本身的日志级别
  2. 面试必备:HashMap底层数据结构?jdk1.8算法优化,hash冲突,扩容等问题
  3. 警惕Oracle DB操作高压线
  4. VS 调用外部DLL时提示“无法嵌入互操作类型”
  5. 计算机时代 英语,雅思8分范文:计算机时代教师角色 【出国英语】
  6. 比较创建几种线程的方式
  7. java使用validator进行校验
  8. 聊聊并发(四)——深入分析ConcurrentHashMap
  9. 传图识字java_Java:全面 清晰的 NIO 学习攻略
  10. centos7配置jdk1.8环境变量