You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两种自旋锁实现效率对比:添加test()调用的影响分析

自旋锁实现效率对比与内存序影响分析

两种自旋锁实现的效率对比

带内层只读自旋(调用test(std::memory_order_relaxed))的实现效率通常更高,核心原因在于:

  • 反复调用test_and_set()属于原子写操作,会触发缓存一致性协议的总线事务(比如MESI协议中的RFO请求),频繁写操作会占用大量总线带宽,拉低其他核心的缓存命中率,整体性能损耗大。
  • 内层用test()只读自旋时,仅读取原子变量状态,缓存未失效的情况下可直接从本地缓存读取,不会触发总线事务,能大幅减少总线竞争,降低对其他核心的干扰。

添加/移除lock.test(std::memory_order_relaxed)的影响

添加内层test()调用的情况

外层test_and_set()尝试获取锁失败后,进入内层低开销自旋:

  • memory_order_relaxed内存序保证读取操作的原子性,但不参与内存同步,不会生成内存屏障,执行开销极低。
  • 当锁被释放时,持有锁的核心执行clear(std::memory_order_release)会同步锁状态到全局内存,其他核心缓存会收到失效通知,此时内层自旋会检测到状态变化,退出内层循环后再尝试外层的test_and_set()。
  • 对应汇编代码会生成“尝试获取锁+失败后低开销等待”的逻辑,有效减少总线竞争。

移除内层test()的情况

直接在外层循环反复调用test_and_set():

  • 每次循环都执行原子写操作,即便锁处于占用状态,也会持续发起总线事务,导致总线带宽被大量占用,其他核心的操作会被阻塞,整体性能明显下降。
  • 对应汇编代码会反复执行带原子操作的指令,没有低开销的自旋等待逻辑。

代码示例

#include <atomic>

#define METHOD 1

int main( )
{
    std::atomic_flag lock { };

#if METHOD == 1
    while ( lock.test_and_set( std::memory_order_acquire ) )
    {
        while ( lock.test( std::memory_order_relaxed ) );
    }
#else
    while ( lock.test_and_set( std::memory_order_acquire ) );
#endif

    lock.clear( std::memory_order_release );
}

内容的提问来源于stack exchange,提问作者digito_evo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:17:26