本篇文章将以Intel CPU作为讨论基础

一、并发的由来

  1. 一台计算机有2个cpu,其中CPU1执行程序A,CPU2执行程序B,由于程序A和程序B是两个不同的应用程序,所以它们两个之间并不存在并发问题。

2.现在两个CPU要执行程序A的同一段代码,比如对变量a执行加1操作,代码a=a+1经过汇编器编译之后就是如下指令片段:addl $1,-4(%esp);

Intel CPU的指令集属于复杂指令集类型(CISC),其内部也是由微指令组成,就拿上面的加1操作指令,在CPU内部执行的时候可能会分成如下三步:

(1)从内存中取到1放入寄存器中

movl -4(%ebp),%eax

(2)对寄存器中的数执行加1操作

addl $1,%eax

(3)将加操作的结果写回内存中

movl %eax,-4(%ebp)

3.那么问题就来了:由于执行的是同一段代码,我们期望最后的结果是两个CPU各加一次,也就是a=3。但实际情况存在穿插执行:CPU1和CPU2同时执行了步骤1,此时a=1;然后CPU2执行了加法操作并把数据写入了内存,此时a=2,但CPU1已经取到的值是1,执行加法指令操作,接着把结果写入内存,结果依然是a=2。与我们预期的a=3不符,造成数据紊乱。造成数据紊乱的根本原因就是穿插执行,多个CPU操作同一个可读可写的数据就会有并发问题。那在CPU层面是如何解决并发问题呢?

二、CPU解决并发问题的方案

1.对总线上锁

为了解决并发问题,我们能想到的就是把以上三个步骤的代码当作一个整体,要么全部不执行,要么全部执行不能被穿插,我们称之为原子性代码:将一串操作定义为不能拆散的基本操作。

CPU在访存的时候需要通过控制总线、数据总线和地址总线相结合从内存读写数据,由此可以得知第一种解决办法就是对总线上锁。但这种方法有个很大的弊端,一旦锁了总线,就算其他CPU执行的不是同一个程序的代码,那么这些CPU也得等待,这将造成严重的性能损耗,锁的粒度太大,为此我们考虑如何将锁细粒度化?

2.对缓存行上锁

CPU内部有缓存,为了加速访问,CPU会把数据a相邻连续的一段内存空间数据(缓存行)加载到缓存中,为此得到了我们第二种解决数据紊乱的办法:对缓存行上锁。一旦数据a发生改变,会根据CPU的MESI协议来更新数据,达到数据一致性。[关于CPU的MESI协议可以参考本篇文章]

3.原子性指令

综上所述,intel cpu提供了原子性指令,只要指令支持lock前缀,那么它就可以把这条指令变成原语指令(原语:原子性的语义),比如 add,加上lock前缀就是 lock;add ,那么加法操作就变成了原子性操作,不会再被穿插执行了。但也有一些指令比较特殊,它们本身就是原语指令,不需要lock前缀,比如:xchg。

三、上层应用的并发解决方案

只有CPU提供了原子性指令,上层应用才能够根据这些指令来设计出指令段与指令段之间的原子性操作。这是一种自底向上的设计,没有CPU最底层的支持,上层应用根本就无法解决并发问题。应用程序使用自身语言提供的并发操作函数库,比如java的juc包,而这些函数库又会封装OS的系统调用或者使用glibc库,OS的系统调用最终会使用CPU提供的原子性指令。

并发原理 — CPU原子性指令(一)的更多相关文章

  1. java高并发核心要点|系列4|CPU内存指令重排序(Memory Reordering)

    今天,我们来学习另一个重要的概念. CPU内存指令重排序(Memory Reordering) 什么叫重排序? 重排序的背景 我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多.当CP ...

  2. 【Java虚拟机5】Java内存模型(硬件层面的并发优化基础知识--指令乱序问题)

    前言 其实之前大家都了解过volatile,它的第一个作用是保证内存可见,第二个作用是禁止指令重排序.今天系统学习下为什么CPU会指令重排. 存储器的层次结构图 1.CPU乱序执行指令的根源 CPU读 ...

  3. 单片机、CPU、指令集和操作系统的关系

    郑重声明:转载自http://blog.csdn.net/zhongjin616/article/details/18765301 1> 首先讨论各种单片机与操作系统的关系 说到单片机,大家第一 ...

  4. cpu读取指令时读取的长度

    CPU读取指令时,如果单字节指令,一次访存即可完成读取操作:如果是多字节指令,会根据第一次读取指令的操作码与寻址标志位,判断指令的后续长度,进而完成整个指令的读取,同时指令指针IP会自动进行修改,指向 ...

  5. MySQL InnoDB 实现高并发原理

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  6. Python 之并发编程之进程上(基本概念、并行并发、cpu调度、阻塞 )

    一: 进程的概念:(Process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位. 资源分配:分配的是cpu和内存等物理资源 进程号是进程的唯一标识 同一个程序执行两次之后是两个进程 ...

  7. 并发编程-CPU执行volatile原理探讨-可见性与原子性的深入理解

    volatile的定义 Java语言规范第3版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量.Jav ...

  8. CPU 多核指令 —— WFE 原理【原创】

    转自:http://tinylab.org/arm-wfe/ Zhang Binghua 创作于 2020/05/19 打赏 微信公众号   知识星球 关注 @泰晓科技 与数千位一线 Linux 工程 ...

  9. 【多线程与高并发原理篇:4_深入理解synchronized】

    1. 前言 越是简单的东西,在深入了解后发现越复杂.想起了曾在初中阶段,语文老师给我们解说<论语>的道理,顺便给我们提了一句,说老子的无为思想比较消极,学生时代不要太关注.现在有了一定的生 ...

随机推荐

  1. 机器学习-K近邻(KNN)算法详解

    一.KNN算法描述   KNN(K Near Neighbor):找到k个最近的邻居,即每个样本都可以用它最接近的这k个邻居中所占数量最多的类别来代表.KNN算法属于有监督学习方式的分类算法,所谓K近 ...

  2. CADisplayLink、NSTimer循环引用解决方案

    前言:CADisplayLink.NSTimer 循环引用问题 ​ CADisplayLink.NSTimer会对Target产生强引用,如果target又对他们产生强引用,那么就会引发循环引用. @ ...

  3. 阿里 Maven仓库

    <?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...

  4. 数码管动态显示Verilog实现(参考小梅哥教程)(视觉暂留)

    一个数码管有九个引脚,控制八段二极管的亮灭,用以显示需要的数字. 当有N个数码管时,一个一个控制的话需要N x 9 个引脚,消耗资源较多. 因此可以利用动态显示的方案通过人眼的视觉暂留特性达到静态显示 ...

  5. 【一本通提高组合数学】 计算系数(NOIP2011提高组)

    题面 思路 根据二项式定理, 那么 算  需要用快速幂. 可以根据组合式的递推公式算组合数.我是这么写的. 或者是利用组合数的定义式,但是因为有取余, 所以要用逆元. 其中  为逆元, 这个可以直接用 ...

  6. angular变更检测相关文章

    你需要了解的关于Angular 变更检测的一切 If you think `ngDoCheck` means your component is being checked - read this a ...

  7. 20220723-Mac上使用IntelliJ IDEA

    目录 IDEA快捷键 IDEA模板 常用模板快捷键 个人随笔 软件:IntelliJ IDEA 电脑:Mac IDEA快捷键 打开/关闭 项目视图 快捷键:⌘ + 1 运行项目 快捷键:⌃ + ⇧ + ...

  8. ABP 6.0.0-rc.1的新特性

      2022-07-26官方发布ABP 6.0.0-rc.1版本,本文挑选了几个新特性进行了介绍,主要包括LeptonX Lite默认主题.OpenIddict模块,以及如何将Identity Ser ...

  9. GreatSQL重磅特性,InnoDB并行并行查询优化测试

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1 ...

  10. Mac设置外网访问本地项目

    > 官网地址:https://ngrok.com/download 步骤(官网基本已经说明了步骤,但还不完善,以下为亲测步骤): 下载并注册账号 打开终端,进入ngrok.zip所在文件夹(方法 ...