自旋锁与竞争:指数回退和队列锁的实现与优化
1. 自旋锁性能问题分析
在多线程环境中,自旋锁的性能受到多种因素的影响。以 TASLock 为例,自旋线程几乎每次都会遇到缓存未命中的情况,需要使用总线来获取新的但未改变的值。当持有锁的线程尝试释放锁时,由于总线被自旋线程垄断,可能会导致延迟。这就是 TASLock 性能不佳的原因。
而 TTASLock 算法在性能上有所改进。当线程 A 持有锁时,线程 B 第一次读取锁会发生缓存未命中,需要等待值加载到其缓存中。只要 A 持有锁,B 重复读取该值时都会命中缓存,不会产生总线流量,也不会减慢其他线程的内存访问。然而,当锁被释放时,情况会恶化。锁持有者将锁变量写为 false,这会使自旋线程的缓存副本失效,它们都会重新读取新值,并几乎同时调用 getAndSet() 来获取锁,导致总线流量激增。
1.1 局部自旋的重要性
局部自旋是指线程反复读取缓存值而不是反复使用总线,这是设计高效自旋锁的重要原则。通过减少总线流量,可以提高锁的性能。
2. 指数回退算法
2.1 回退的必要性
在 TTASLock 算法中,当多个线程同时尝试获取锁时,会产生竞争。如果在读取锁和尝试获取锁的两个步骤之间,有其他线程获取了锁,很可能存在高竞争。在高竞争情况下尝试获取锁会增加总线流量,且线程获取锁的机会渺茫。因此,线程应该回退一段时间,让竞争线程有机会完成操作。
2.2 回退时间的确定
一个好的经验法则是,不成功尝试的次数越多,竞争可能越高,线程回退的时间应该越长。每次线程看到锁变为可用但未能获取时,会在重试前进行回退。为了
超级会员免费看
订阅专栏 解锁全文
10万+

被折叠的 条评论
为什么被折叠?



