当前位置:网站首页>原子操作 CAS
原子操作 CAS
2022-07-31 02:57:00 【JACKSONMHLN】
参考:
https://zhuanlan.zhihu.com/p/400817892
https://www.bilibili.com/read/cv10686883/
https://blog.csdn.net/www_dong/article/details/119920236
https://blog.csdn.net/niu91/article/details/116308436
https://blog.csdn.net/CringKong/article/details/79966161
1、原子操作
原子操作,不会被线程调度机制打断的操作。这个操作一旦开始,就一直运行到结束,中间不会有任何上下文切换。
典型的原子操作有(原子操作需要硬件支持)
Load / Store :读写内存
Test and Set:针对bool变量,如果为true则返回true,如果为false,则将变量置为true并返回false。
Clear:将bool变量设为false。
Exchange:将指定位置的值设置为传入值,并返回其旧值。
Compare and Swap:将指定位置的值与期望值比较,如果相等则赋值为新值,如果不等则将期望值设置为自身。返回是否设置成功。
Fetch And 加减乘除系列:对指定位置的值使用传入参数执行加减乘除,并返回旧值。
2、竞态条件(Race Conditon)
int i = 0;
i++;
mov eax,dword ptr [i] // 将i加载到eax寄存器
add eax,1 // eax中的值加一
mov dword ptr [i],eax // 将eax中的值赋值到i的地址 汇编层面有三步操作:读-修改-写。线程1修改完还未写到内存中去,线程2得到CPU开始执行,修改的会是线程1未写到内存中的值,存在线程安全问题。
4、线程安全
解决线程安全通常有以下方法:
1、使用原子操作。
2、加锁:悲观锁或者乐观锁(无锁)
1、atomic_int num; num++;
在msvc中,C++11 提出的 atomic_int 类型,在 num++ 操作时,底层调用windows提供的原子自增函数_InterlockedIncrement 。
2、悲观锁
mutex 就是一种悲观锁的使用。假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
3、乐观锁
假设不会发生并发冲突,每次不加锁而是假设没有冲突而去完成某项操作,只在提交操作时检查是否违反数据完整性。
CAS (Compare And Swap)操作是一条CPU的原子指令,所以不会有线程安全问题。
CAS(addr,old,new)解释:将addr存放的只与old比较,如果等于old,则将new赋值给addr。
C++ 可以实现如下:
bool compare_and_swap(int* pAddr, int nExpected, int nNew) {
if (*pAddr == nExpected) {
*pAddr = nNew;
return true;
}
else
return false;
}不同编译器 底层实现不一样,但算法思想一样。
GCC的CAS,GCC4.1+版本中支持CAS的原子操作。
1)bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)
2)type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)C++11中的CAS,C++11中的STL中的atomic类的函数可以让你跨平台。
template< class T > bool atomic_compare_exchange_weak( std::atomic* obj,T* expected, T desired );
template< class T > bool atomic_compare_exchange_weak( volatile std::atomic* obj,T* expected, T desired );Windows的CAS
InterlockedCompareExchange ( __inoutLONGvolatile *Target,
__inLONGExchange,
__inLONGComperand);CAS 存在的问题: ABA。
解决方法: Double CAS,即可以加上版本号。
像状态寄存器、映射到内存地址上的 I/O 操作、涉及硬件操作的变量需要加volatile,因为对它们的每一次操作都有其意义,
而并发时,多线程多任务环境下各任务间共享的标志,其实更应该用原子量和内存序,或者直接加互斥锁,以确保共享区操作的原子性和顺序性。
所以其实volatile和atomic是应用于不同场景的,甚至可以叠加使用。比如:
volatile std::atomic<int> value;
这个式子表示对value的操作都是原子性的,
边栏推荐
- Linux下redis7的安装,启动与停止
- The principle of complete replication of virtual machines (cloud computing)
- 局域网电脑硬件信息收集工具
- The use of font compression artifact font-spider
- SQALE 是什么
- try-catch中含return
- 【CV项目调试】CUDNN_CONVOLUTION_FWD_SPECIFY_WORKSPACE_LIMIT问题
- 共模电感的仿真应用来了,满满的干货送给大家
- Software accumulation -- Screenshot software ScreenToGif
- 拒绝加班,程序员开发的效率工具集
猜你喜欢

【Android】Room —— SQLite的替代品

【C语言】三子棋(经典解法+一览图)

刚出道“一战成名”,安全、舒适一个不落

CorelDRAW2022 streamlined Asia Pacific new features in detail

分布式与集群是什么 ? 区别是什么?

学习DAVID数据库(1)

公司官网建站笔记(六):域名进行公安备案并将备案号显示在网页底部

11、Redis实现关注、取消关注以及关注和粉丝列表

Local area network computer hardware information collection tool

Mycat's master-slave relationship, vertical sub-database, horizontal sub-table, and detailed configuration of mycat fragmented table query (mysql5.7 series)
随机推荐
Classic linked list OJ strong training problem - fast and slow double pointer efficient solution
刚出道“一战成名”,安全、舒适一个不落
测试中的误报和漏报同样的值得反复修正
f.grid_sample
print task sorting js od huawei
【C语言】表达式求值的一般方法
LeetCode Daily Question 2022/7/25-2022/7/31
Discourse 自定义头部链接(Custom Header Links)
多线程下类对象的服务承诺探讨
CorelDRAW2022 streamlined Asia Pacific new features in detail
LeetCode 每日一题 2022/7/25-2022/7/31
4、敏感词过滤(前缀树)
基于opencv实现人脸检测
LeetCode 1161 The largest element in the layer and the LeetCode road of [BFS binary tree] HERODING
跨专业考研难度大?“上岸”成功率低?这份实用攻略请收下!
SQL注入 Less47(报错注入) 和Less49(时间盲注)
Hanyuan Hi-Tech 8-channel HDMI integrated multi-service high-definition video optical transceiver 8-channel HDMI video + 8-channel two-way audio + 8-channel 485 data + 8-channel E1 + 32-channel teleph
StringJoiner详解
编译Hudi
C#远程调试