一、概念
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协议。
![](https://img-blog.csdnimg.cn/direct/1336ca8e5f66442e93a133b89c8fc2ea.png)
![](https://img-blog.csdnimg.cn/direct/ab1efcc624df4da09bbbfe4bf1ac2974.png)
![](https://img-blog.csdnimg.cn/direct/2dd2d8bb91af4f2ca5f22b6d8d8a79bd.png)
分享一个学习链接,有需要的同学可以看一下: