原子操作CAS与锁实现一

一、概念

1.什么是原子操作:

      多线程环境下,确保对共享变量的操作在执行时不会被干扰,从而避免竞态条件.

2.互斥锁、自旋锁、原子变量的原理:

(1).互斥锁:当有一个线程使用互斥锁时,其它线程会先在用户空间自旋等待锁释放,自旋结束没有等到锁释放,会进入内核空间的阻塞队列,当锁释放,线程转入就绪态等待。

(2).自旋锁:当一个线程进入互斥锁时,其它线程会自旋等待锁释放,不会进入阻塞态。

当锁中的程序执行时间过长使用互斥锁,时间短使用自旋锁。

(3).原子变量:将一个变量的操作步骤抽象成一个原子,当一个线程执行时其他线程无法操作该变量。

二、原子性实现

1.单处理器单核情况:只要保证操作指令不被打断,底层使用的是自旋锁

2.多处理器或者多核:除了不被打断还要避免其他核心操作相关内存空间,以往0x86会使用lock指令锁总线,避免所有内存访问总线,现在lock指令只组织其它核心对相关内存空间的访问。

多处理器或者多核的存储体系结构:cpu cache,cpu缓存操作的最小单位,解决cpu运行速度与内存访问速度不匹配问题。

cpu如何使用cpu cache读取数据:使用写回策略,延迟写入读取到内存。

写操作:通过cache中的tag字段区域的操作检查缓存中是否存在操作的变量(缓存命中),存在标记为脏数据,不存在往下寻找空闲内存,并标记为脏,如果都不存在,则通过LRU将缓存中的最近最少使用的脏数据写入主存,将需要操作的数据写到该位置,标记为脏数据。 

读操作:第一步还是检查命中缓存,命中直接读返回;没有命中继续往下,不存在则通过LRU将主存数据写入到缓存,标记为非脏数据。

使用写回策略在一个处理器多核情况下可能出现就缓存不一致问题:就是当一个核心修改变量,还未写入主存,另一个核心从主存读取到该变量以前的值。

如何解决缓存不一致问题:

写传播:总线嗅探bus snooping当一个核心写入时,其它核心可以监听;

事务串行化:通过锁和lock指令实现,读取缓存时,对同一个变量处理时,同一个处理器下的核心比其它处理器的核心获取数据的优先级更高。例如,当A处理器中,核心a先写入i=10,B处理器中核心a后写入i=20,A处理器中核心b读取i,读取到的值会是10并不是20.

优化,减少写传播中给总线带宽的压力:当一个核心并没有操作该变量时,并不需要接收到关于该变量的广播,实现方式MESI协议。

缓存一致性协议 MESI:
MESI 协议是一个基于失效的缓存一致性协议,支持 write-back 写回缓存的常用协议。
主要原理:通过总线嗅探策略(将读写请求通过总线广播给所 有核心,核心根据本地状态进行响应)
状态
Modified M ):某数据已修改但是没有同步到内存中。如果其 他核心要读该数据,需要将该数据从缓存同步到内存中,并将状 态转为 S
Exclusive E ):某数据只在该核心当中,此时缓存和内存中的 数据一致。
Shared S ):某数据在多个核心中,此时缓存和内存中的数据 一致。
Invaliddate I ):某数据在该核心中以失效,不是最新数据。
事件
PrRd :核心请求从换存块中读出数据;
PrWr :核心请求向缓存块写入数据;
BusRd :总线嗅探器收到来自其他核心的读出缓存请求;
BusRdX :总线嗅探器收到另一核心写⼀个其不拥有的缓存块的 请求;
BusUpgr :总线嗅探器收到另一核心写⼀个其拥有的缓存块的 请求;
Flush :总线嗅探器收到另一核心把一个缓存块写回到主存的请 求;
FlushOpt :总线嗅探器收到一个缓存块被放置在总线以提供给 另一核心的请求,和 Flush 类似,但只不过是从缓存到缓存的传 输请求。
状态机 状态机详解
写后锁住ME两种状态,避免相关内存的访问。
最终实现只有一个核心可以操作变量。

分享一个学习链接,有需要的同学可以看一下:

https://xxetb.xetslk.com/s/3yNycZ

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值