上交os lec8 同步原语
8.1 临界区问题
- os提供同步原语,防止共享资源的竞争错误
- 解决临界区问题三个要求,互斥访问,优先等待,空闲让进
![]()
8.2 互斥锁的软件实现与硬件实现
- 皮特森算法
![]()
- 关中断只能够解决单个CPU核上的临界区问题,但是多核不行
![]()
- 互斥锁还可以实现同步互斥访问
![]()
intel通过锁总线实现原子的CAS
对于任意地址的修改都要经过总线,通过锁总线来实现原子操作 - arm使用LL/SC实现原子操作
![]()
![]()
- FAA获取并增加也可是一种硬件实现锁的方式
- 自旋锁
![]()
![]()
- 排号锁
用FAA实现排号锁![]()
![]()
- 排号锁和spinlock都是mutex的
8.3 读写锁
读写锁![]()
![]()
- 读写锁的偏向性
也就是读者优先还是写者优先 - 读者优先
![]()
8.4 Read Copy Updat e
- 如何提高读者的效率,使用RCU
读者要么看到旧的值,要么看到新的值
硬件的原子操作最多只能128bit
由于硬件的原子操作最多只能128bit,那么可以通过修改指针的操作来修改一块内存区域,现在不用加🔒
这里读者要么读到data-c,要么读到data-c',但是局限性在于什么时候回收废弃的内存
同时需要临时拷贝旧内存- RCU宽限期
![]()
需要确定每一个读者何时进入已经退出灵界区
这样才可以更好的回收旧节点![]()
- 管程,是提供一系列thread-safe的接口,开发者直接使用这些接口
![]()
RCU写者需要处理节点拷贝
8.5 死锁
![]()
- 四种产生死锁的原因
![]()
8.6 优先级反转
锁的使用导致进程顺序不按照优先级执行- NCP
获取了锁之后不许被打断 - 原生优先级置顶协议
![]()
![]()
8.7 性能可扩展性
- 单核性能已经遇到了瓶颈,现在是多核时代
![]()
- 由于多核,为了正确性,需要加锁,那么多核本就是为了性能
![]()
- amdahl定律,可以并行的代码占比越大以及核数越多,那么加速比S越大
![]()
- 基准测试是指你可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途。其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件,等等
8.8 缓存一致性
- 多核情况下的缓存模型
多级缓存,每一个CPU核有自己的一个L1 cache
L3 cache又叫做last level cache
多种缓存一致性协议MESI?MSI![]()
- 缓存一致性协议中e(exclusive)适当一个缓存行本地写之后
![]()
- 每次从memory中load cache行时,需要更新全局共享目录
![]()
- 当一个cpu修改了一个cache line,bit vector会将其他bit置0
也就是说,写cache需要等待全局目录项通知CPU可以修改
这里888覆盖233是基本的硬件层面的覆盖 - 可扩展性断崖,如果多个核都要写
那么对于全局目录项的写存在大量的竞争,多个核交互 过多
访问一次l1 cache的时间是3个cycle,但是当核的数量非常多时,从远端访问数据时,需要121 cycle,那么p(可以并行的代码时间占比) - 通过back-off解决问题,也就是对于单一缓存行的竞争等待一段时间,之后指数后退等待时间
![]()
8.9 MCS锁
- spinlock竞争,是其中一个CPU将1置为0(也就是释放锁),那么其他的CPU都会去争抢那个🔒,
![]()
- MCS锁的原理是不去争抢,而是排队
原子操作更新MCS锁指针![]()
- 释放最后一个节点时,又来一个节点,这时会出现两种情况
不会再发生高频竞争全局缓存行
可以看到紫色的线
linux kernel中已经运用了MCS锁![]()
8.10 非一致性内存访问
- 硬件提供私有高速缓存的正确性
两个cpu同时访问同一个cacheline - NUMA节点
![]()
- NUMA本地锁与全局锁
![]()





intel通过锁总线实现原子的CAS
对于任意地址的修改都要经过总线,通过锁总线来实现原子操作



用FAA实现排号锁

读写锁

也就是读者优先还是写者优先
读者要么看到旧的值,要么看到新的值
硬件的原子操作最多只能128bit
由于硬件的原子操作最多只能128bit,那么可以通过修改指针的操作来修改一块内存区域,现在不用加🔒
这里读者要么读到data-c,要么读到data-c',但是局限性在于什么时候回收废弃的内存
同时需要临时拷贝旧内存
需要确定每一个读者何时进入已经退出灵界区
这样才可以更好的回收旧节点

RCU写者需要处理节点拷贝

锁的使用导致进程顺序不按照优先级执行
获取了锁之后不许被打断




多级缓存,每一个CPU核有自己的一个L1 cache
L3 cache又叫做last level cache
多种缓存一致性协议MESI?MSI


也就是说,写cache需要等待全局目录项通知CPU可以修改
这里888覆盖233是基本的硬件层面的覆盖
那么对于全局目录项的写存在大量的竞争,多个核交互 过多
访问一次l1 cache的时间是3个cycle,但是当核的数量非常多时,从远端访问数据时,需要121 cycle,那么p(可以并行的代码时间占比)

原子操作更新MCS锁指针
不会再发生高频竞争全局缓存行
可以看到紫色的线
linux kernel中已经运用了MCS锁
两个cpu同时访问同一个cacheline

浙公网安备 33010602011771号