聊聊CPU的LOCK指令
本文转载自聊聊CPU的LOCK指令
导语
在多线程操作中,可能最经常被提起的就是数据的可见性、原子性、有序性。不管是硬件方面、软件方面都在这三方面做了很足的工作,才能保证程序的正常运行。
之前发表过一篇文章聊聊缓存一致性协议 如果感兴趣的话可以去阅读一下,里面谈到了缓存一致性的实现和处理过程,读完之后可以仔细去细想一下缓存一致性协议
到底解决了什么问题。个人理解缓存一致性协议
解决了CPU层面的可见性和一致性问题,阅读到这里可以在这里停下来,仔细回想一下缓存一致性的原理,它通过监听共享总线上消息,对自己缓存中的数据修改不同的状态,来保证数据的一致性,对自己缓存中的数据失效后,下次读取会从主存中直接读取最新的数据 ,可以保证可见性,同时保证各缓存中的数据是一致的。
软件的并发编程一样,其实除了可见性、有序性,在计算机指令在执行的过程中,CPU通过不停地切换线程执行,给每个线程分配CPU时间片来实现多线程机制,一定也会存在原子性问题,在计算机层面是怎么解决原子性问题的,这就我们今天要聊的LOCK#指令,有时也被我们称为总线锁。
LOCK指令作用
在Intel 64 and IA-32 Architectures Software Developer’s Manual 中的章节LOCK—Assert LOCK# Signal Prefix 中给出LOCK指令的详细解释
大至翻译之后的意思如下
在CPU的LOCK信号被声明之后,在此期随同执行的指令会转换成原子指令。在多处理器环境中,LOCK信号确保,在此信号被声明之后,处理器独占使用任何共享内存。
在不大多数IA-32和Inter64位处理器中,锁可能在没有LOCK#信号的时情况下发生。请参阅下面的“IA32体系结构兼容性”部分的详细内容。
LOCK前缀只能预加在以下指令前面,并且只能加在这些形式的指令前面,其中目标操作数是内存操作数:
add、adc、and、btc、btr、bts、cmpxchg、cmpxch8b,cmpxchg16b,dec,inc,neg,not,or,sbb,sub,xor,xadd
和xchg
。如果LOCK前缀用上述列表中的指令并且源操作数是内存操作数(也就是指令没有对内存进行写操作),可能会出现未定义的
操作码异常
(ud)。如果锁前缀与任何不在上面列表中的指令一起使用,也将生成未定义的操作码异常。
xchg
指令不管有没有声明LOCK前缀,总是会声明LOCK信号。锁定前缀通常与BTS指令一起使用,在共享内存环境中,以对内存地址执行
读-修改-写
操作。锁定前缀的完整性不受内存字段对齐的影响。对于任意未对齐的字段,可以观察到内存锁定。
此指令的操作在非64位模式和64位模式下是相同的。
从P6系列处理器开始,当使用 LOCK 指令访问的内存已经被处理器加载到缓存中时,LOCK# 信号通常不会断言。取而代之的是,只锁定处理器的缓存。在这里处理器的缓存一致性机制确保对内存进行的操作是原子性的。请参见“锁定操作对内部处理器缓存的影响”,在Intel64和IA-32体系结构软件开发人员手册第3A卷第8章中,有关锁定缓存的详细信息。
大致翻译差不多如上,核心意思主要说明LOCK指令在声明之后通过锁定总线,独占共享内存,通过一种排它的思想确保当前对内存操作的只有一个线程,然后确定在这段声明期间指令执行不会被打断,来保证其原子性。
处理器如何实现原子操作
首先处理器会保证基本的内存操作的原子性,比如从内存读取或者写入一个字节是原子的,但对于读-改-写
、或者是其它复杂的内存操作是不能保证其原子性的,又比如跨总线宽度
、跨多个缓存行
和夸页表的访问
,这时候需要处理器提供总线锁
和缓存锁
两个机制来保证复杂的内存操作原子性
总线锁
LOCK#信号就是我们经常说到的总线锁,处理器使用LOCK#信号达到锁定总线,来解决原子性问题,当一个处理器往总线上输出LOCK#信号时,其它处理器的请求将被阻塞,此时该处理器此时独占共享内存。
总线锁这种做法锁定的范围太大了,导致CPU利用率急剧下降,因为使用LOCK#是把CPU和内存之间的通信锁住了,这使得锁定时期间,其它处理器不能操作其内存地址的数据 ,所以总线锁的开销比较大。
缓存锁
如果访问的内存区域已经缓存在处理器的缓存行中,P6系统和之后系列的处理器则不会声明LOCK#信号,它会对CPU的缓存中的缓存行进行锁定,在锁定期间,其它 CPU 不能同时缓存此数据,在修改之后,通过缓存一致性
协议来保证修改的原子性,这个操作被称为“缓存锁”
什么情况下使用总线锁(LOCK#)
当操作的数据不能被缓存在处理器内部,或操作的数据跨多个缓存行时,也会使用总线锁
因为从P6系列处理器开始才有缓存锁,所以对于早些处理器是不支持缓存锁定的,也会使用总线锁
有些指令自带总线锁
BTS、BTR、BTC 、XADD、CMPXCHG、ADD、OR
等,这些指令操作的内存区域就会加锁,导致其它处理器不能同时访问它。
在上面指令中的CMPXCHG
就是JAVA里面CAS
底层常用的指令,这个指令在执行的时候,会自动加总线锁保,导致其它 处理器不能同时访问,证其原子性。
LOCK#作用总结
- 锁总线,其它CPU对内存的读写请求都会被阻塞,直到锁释放,因为锁总线的开销比较大,后来的处理器都采用锁缓存替代锁总线,在无法使用缓存锁的时候会降级使用总线锁
- lock期间的写操作会回写已修改的数据到主内存,同时通过缓存一致性协议让其它CPU相关缓存行失效
写在最后
总线锁
、缓存锁
可以保证原子性
,缓存一致性协议
可以保证可见性
,那么JAVA中的内存模型,它做了些什么?下一篇聊聊JAVA中的内存模型(JMM)聊聊JMM
聊聊CPU的LOCK指令的更多相关文章
- 【操作系统之十一】任务队列、CPU Load、指令乱序、指令屏障
一.CPU Loadcpu load是对使用或者等待cpu进程的统计(数量的累加):每一个使用(running)或者等待(runnable)CPU的进程,都会使load值+1;每一个结束的进程,都会使 ...
- 关于缓存一致性协议、MESI、StoreBuffer、InvalidateQueue、内存屏障、Lock指令和JMM的那点事
前言 事情是这样的,一位读者看了我的一篇文章,不认同我文章里面的观点,于是有了下面的交流. 可能是我发的那个狗头的表情,让这位读者认为我不尊重他.于是,这位读者一气之下把我删掉了,在删好友之前,还叫我 ...
- 深入设计电子计算器(一)——CPU框架及指令集设计
版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/8278418.html 作者:窗户 Q ...
- 使用logisim搭建单周期CPU与添加指令
使用logisim搭建单周期CPU与添加指令 搭建 总设计 借用高老板的图,我们只需要分别做出PC.NPC.IM.RF.EXT.ALU.DM.Controller模块即可,再按图连线,最后进行控制信号 ...
- CPU结构与指令执行过程简介
CPU(Central Processing Unit)是计算机中进行算术和逻辑计算处理指令的主要部件. CPU结构 CPU由通用寄存器组,运算器,控制器和数据通路等部件组成. 寄存器包括 数据寄存器 ...
- CPU流水线与指令乱序执行
青蛙见了蜈蚣,好奇地问:"蜈蚣大哥,我很好奇,你那么多条腿,走路的时候先迈哪一条啊?" 蜈蚣听后说:"青蛙老弟,我一直就这么走路,从没想过先迈哪一条腿,等我想一想再回答你 ...
- 使用CPU的AVX指令
arch:AVX 很抱歉GCC还不行……有……倒是 但是不是这么写的 我忘记了……官网上有 http://www.oschina.net/news/66980/kreogist-0-9
- java并发编程知识点备忘
最近有在回顾这方面的知识,稍微进行一些整理和归纳防止看了就忘记. 会随着进度不断更新内容,比较零散但尽量做的覆盖广一点. 如有错误烦请指正~ java线程状态图 线程活跃性问题 死锁 饥饿 活锁 饥饿 ...
- 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则
前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...
随机推荐
- java 读取text内容
public static String readToString(String fileName) { String encoding = "UTF-8"; File file ...
- [SpringSecurity] UserDetailsService 详解
UserDetailsService 接口 当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的. 而在实际项目中账号和密码都是从数据库中查询出来的. 所以我们要通过自定 ...
- CF 1244 C - The Football Season
C - The Football Season 先考虑求解 \[ x\times w + y\times d=p \] 若存在一组解 \[ \begin{cases} x_0\\ y_0 = kw + ...
- 最短Hamilton路径(状压dp)
最短Hamilton路径实际上就是状压dp,而且这是一道作为一个初学状压dp的我应该必做的题目 题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 ...
- Codeforces Round #648 (Div. 2) A. Matrix Game
题目链接:https://codeforces.com/contest/1365/problem/A 题意 给出一个 $n \times m$ 的网格,两人轮流选择一个所在行列没有 $1$ 的方块置为 ...
- Codeforces Round #636div3 D. Constant Palindrome Sum (划分区间,差分)
题意:给你一个长度为偶数n的数组,每次可以将一个元素修改为不大于k的值,要求每个a[i]+a[n-i+1]都相等,求最少操作多少次 题解:假设每一对的和都为sum,小的记为mn,大的记为mx; ...
- P3376 【模板】网络最大流——————Q - Marriage Match IV(最短路&最大流)
第一道题是模板题,下面主要是两种模板,但都用的是Dinic算法(第二个题也是) 第一题: 题意就不需要讲了,直接上代码: vector代码: 1 //invalid types 'int[int]' ...
- Toxophily HDU - 2298 三分+二分
代码+解析: 1 //题意: 2 //有一个大炮在(0,0)位置,为你可不可以把炮弹射到(x,y)这个位置 3 //题目给你炮弹初始速度,让你求能不能找出来一个炮弹射出时角度满足题意 4 //题解: ...
- 金牛来到,福气来到——TcaplusDB新年放送
光阴似箭,2020转瞬间成为历史,牛年的钟声即将敲响,在此,TcaplusDB祝大家新的一年万事如意,牛年带给我们的福气,一定能让我们心想事成! 饮水思源,回顾过去的一年,我们深知,TcaplusDB ...
- read()、readline()、readlines() -- Python
文本文件:readfile.txt 详细描述: read() #一次性读取文本中全部的内容,以字符串的形式返回结果 readline() #只读取 ...