硬件对同步的支持-TAS和CAS指令
现在主流的多处理器架构都在硬件水平上提供了对并发同步的支持。
今天我们讨论两个很重要的硬件同步指令:Test-and-Set和Compare-and-Swap
Test and Set
一个Test-and-Set(TAS)指令包括两个子步骤,把给定的内存地址设置为1,然后返回之前的旧值。
这两个子步骤在硬件上实现为一个原子操作,执行期间不会被其他处理器打断。
(一个CPU可以使用诸如Dual-port RAM电子原件提供的TAS指令,此外,CPU自身也可以提供CAS指令)
值得注意的是,TAS指令是在1位(bit)上实现,这限制了变量非0即1,不会有其他值,并且TAS总是把变量设置为1。
可见,TAS生而为自旋锁,下面是使用TAS实现自旋锁的伪代码[2]:
lock = 0 //shared state
while(test_and_set(lock)==0){ //try lock
//do nothing
}
// 临界区代码
lock = 0 //release
当第一个线程执行这段代码时,TAS指令会立即把lock设置为1,并返回0 ,线程退出while循环进入临界区。
如果另一个线程尝试进入临界区,TAS会把lock设置为1,但是也会返回1(由第一个线程的TAS指令设置为1),
此时第二个线程会一直while循环(忙等待),直到第一个线程退出临界区代码,执行了lock=0,即释放了锁。
这种通过while-loop等待获取锁的实现称为自旋锁(spin lock)。
Compare and Swap
compare-and-swap(CAS)指令和TAS指令类似,但是比TAS要更复杂。
与TAS只有一个参数不同,CAS指令需要三个参数,一个内存位置(V)、一个期望旧值(A)、一个新值(B)。
CAS指令的执行过程:
1.比较内存V的值是否与A相等?
2.如果相等,则用新值B替换内存位置V的旧值
3.如果不相等,不做任何操作。
4.无论哪个情况,CAS都会把内存V原来的值返回。
伪代码:
int CAS(int *ptr,int oldvalue,int newvalue)
{
int temp = *ptr;
if(*ptr == oldvalue)
*ptr = newvalue
return temp;
}
以上过程在CAS指令中是原子操作。
CAS支持32bit/64bit的数据类型,这使得CAS能够实现一些更复杂的自旋锁。
使用CAS实现线程安全的数据结构。
我们使用CAS实现一个并发的平衡二叉搜索树。[1]
基本思路是,所有的更新操作都要在二叉树的副本上进行,更新完成后,使用CAS指令把新的根节点引用替换旧的引用。
//共享变量
root = pointer to the root of the tree
//插入操作
do
old_root = root
new_root = new Tree
# copy old_root into new_root
# do insertion into new_root
until compare_and_swap (root, old_root, new_root) == old_root
平衡操作:
do
old_root = root
new_root = balanced_copy_of (old_root)
until compare_and_swap (root, old_root, new_root) == old_root
如果并行的执行平衡操作和插入操作,插入操作完成后会把二叉树的根节点指向新的引用。
等到平衡操作完成后,compare_and_swap将会失败,因为此时根节点指向了插入操作产生的新地址,不再等于old_root,
平衡操作会重复循环执行,直到成功更新根节点。
同样的,如果平衡操作先于插入操作完成,插入操作的CAS指令也会失败(根节点已指向平衡操作产生的新地址),然后插入操作重复循环,直到成功。
基于CAS指令可以实现基础的信号量、互斥量之外,还可以实现更复杂的lock-free和wait-free算法。
延伸阅读:
1.康奈尔大学操作系统课件:Architectural support for synchronization
2.wiki:Test-and-Set指令
3.wiki:Compare-and-swap指令
4.TAS vs CAS
硬件对同步的支持-TAS和CAS指令的更多相关文章
- Confluence 6 从外部目录中同步数据支持的目录类型
针对一些特定的用户目录类型,Confluence 在系统的数据库中保存了目录的缓存信息(用户和用户组),这样能够让系统更快速的访问用户和用户组数据.一个数据同步的进程将会间歇性的在系统中运行来将远程的 ...
- CAS指令
原文链接:https://www.jianshu.com/p/00edb3d74a33 CAS是CPU的一条指令,其具有原子性,原子性是由CPU硬件层面保证的. CAS原语有三个操作数--内存 ...
- 从ObjectPool到CAS指令
相信最近看过我的文章的朋友对于Microsoft.Extensions.ObjectPool不陌生:复用.池化是在很多高性能场景的优化技巧,它能减少内存占用率.降低GC频率.提升系统TPS和降低请求时 ...
- 【PC桌面软件的末日,手机移动端App称王】写在windows11支持安卓,macOS支持ios,龙芯支持x86和arm指令翻译
面对这场突如其来的变革,作为软件开发者,应该如何选择自己今后的发展方向?桌面软件开发领域还有前景吗? 起源 自从苹果发布m1处理器,让自家Mac支持IOS移动端app运行之后,彻底打破了移动端app和 ...
- CAS(硬件CPU同步原语)
CAS有3个操作数.内存值V,旧的预约值A,要修改后的新值B.当且仅当预期值A和预期值V相同时,将内存值V修改为新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做. 应用1. ...
- 定时自动同步文件,支持多文件夹同步,支持过滤文件和文件夹,解决FileSystemWatcher多次文件触发事件(源码)
博客园里面有很多同步工具和软件,关于FileSystemWatcher类解释的也很多,但收集了很多文章后,感觉没好的方法,自己没事写了一个定时文件同步,借鉴了很多博客园朋友的东西: 上主菜: 配置文件 ...
- Netty的并发编程实践3:CAS指令和原子类
互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能的额外损耗,因此这种同步被称为阻塞同步,它属于一种悲观的并发策略,我们称之为悲观锁.随着硬件和操作系统指令集的发展和优化,产生了非阻塞同步,被称为 ...
- 《java并发编程实战》读书笔记12--原子变量,非阻塞算法,CAS
第15章 原子变量与非阻塞同步机制 近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令(例如比较并交换指令)代替锁老确保数据在并发访问中的一致性. 15.1 锁的劣势 ...
- .NET机器学习 ML.NET 1.4预览版和模型生成器更新
ML.NET 是面向.NET开发人员的开源和跨平台机器学习框架. ML.NET 还包括Model Builder (一个简单的UI工具)和 CLI ,使用自动机器学习(AutoML)构建自定义 ...
随机推荐
- Springboot之actuator未授权访问
copy 子杰的哈,懒的写了 0x01 未授权访问可以理解为需要授权才可以访问的页面由于错误的配置等其他原因,导致其他用户可以直接访问,从而引发各种敏感信息泄露. 0x02 Spring Boot ...
- [05]HTML基础之表格标签
1. <table>标签 表格容器,尽量避免用属性书写样式,而是用CSS来表达 border: 数字 //表格边框宽度 2. <caption>标签 表格的标题,一般出现在表格 ...
- jchdl - GSL实例 - Sub(二的补码实现)
https://mp.weixin.qq.com/s/10fgjqPt2pRvIJzjDGYgBg 概念辨析 <IC-二进制, 自然数, 有符号数>:https://mp.weix ...
- 分享两个常用的rem布局方式
关于rem 这种技术需要一个参考点,一般都是以<body>的“font-size”为基准. 比如我们设置body,html的字体大小为10px:那么1rem就是10px, 这样一来,我们设 ...
- Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
745. 前缀和后缀搜索 给定多个 words,words[i] 的权重为 i . 设计一个类 WordFilter 实现函数WordFilter.f(String prefix, String su ...
- Java实现 蓝桥杯VIP 算法训练 数列
问题描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13,- (该序列实际上就是 ...
- Java实现 LeetCode 229 求众数 II(二)
229. 求众数 II 给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素. 说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1). 示例 1: 输入: [3,2, ...
- java实现数字黑洞
任意一个 5 位数,比如:34256,把它的各位数字打乱,重新排列,可以得到 一个最大的数:65432,一个最小的数 23456. 求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不 ...
- Python学习之温度转换实例分析篇
#TempConvert.py Tempstr=input('请输入要转换的温度值:') if Tempstr[-1] in ['C','c']: F=1.8*eval(Tempstr[0:-1])+ ...
- 实验三 Linux系统用户管理及VIM配置
项目 内容 这个作业属于哪个课程 班级课程的主页链接 这个作业的要求在哪里 作业要求链接接地址 学号-姓名 17041428-朱槐健 作业学习目标 1.学习Linux系统用户管理 2.学习vim使用 ...