# lock-contention-benchmark **Repository Path**: liudegui/lock-contention-benchmark ## Basic Information - **Project Name**: lock-contention-benchmark - **Description**: 多线程同步性能基准测试:Spinlock vs Mutex vs ConcurrentQueue - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-07-01 - **Last Updated**: 2026-02-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: Cpp, 多线程, 性能测试, 无锁, 同步原语 ## README # 锁竞争基准测试 多线程同步策略性能对比: 1. **Spinlock** -- atomic_flag TAS + pause/yield 提示 2. **std::mutex** -- OS 级互斥锁 + lock_guard 3. **ConcurrentQueue** -- moodycamel 无锁 MPMC 队列 ## 构建与运行 ```bash mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j$(nproc) ./lock_test ``` ## 测试方法 | 参数 | 值 | |------|------| | 线程数 | 8 | | 每线程操作数 | 50,000 | | 总操作数 | 400,000 (push 和 pop 严格相等) | | 预热轮次 | 2 (结果丢弃) | | 测量轮次 | 5 (报告 min/median/max) | | SmallItem | 80 bytes (int32_t[20]) | | LargeItem | 4096 bytes (int32_t[1024]) | 关键设计: - 原子 Barrier 同步起跑,所有线程同时开始竞争 - Spinlock 自旋循环加 `pause` (x86) / `yield` (ARM) 提示,减少流水线浪费 - `do_not_optimize()` 编译器屏障,防止 dequeue 结果被优化掉 - ConcurrentQueue 使用 ProducerToken/ConsumerToken 获得最佳吞吐 - 容器统一为 `std::deque`,隔离锁竞争成本,避免 `std::list` 逐元素堆分配干扰 - Release 构建 (-O2 -DNDEBUG) ## 测试结果 ### 测试环境 ``` CPU: AMD Ryzen 7 5800H (8 cores / 16 threads) @ 3.2GHz RAM: 32GB DDR4 OS: Ubuntu 24.04, Linux 6.8.0-79-generic x86_64 Compiler: GCC 13.3.0, -O2 -DNDEBUG ``` ### SmallItem (80 bytes) | 同步策略 | Push min | Push median | Push max | Pop min | Pop median | Pop max | |----------|----------|-------------|----------|---------|------------|---------| | Spinlock + deque | 136.85 ms | 144.45 ms | 150.62 ms | 114.25 ms | 123.02 ms | 128.10 ms | | Mutex + deque | 154.14 ms | 178.89 ms | 186.68 ms | 198.58 ms | 211.40 ms | 215.61 ms | | ConcurrentQueue | 2.78 ms | 2.98 ms | 3.33 ms | 4.08 ms | 4.25 ms | 5.07 ms | ### LargeItem (4096 bytes) | 同步策略 | Push min | Push median | Push max | Pop min | Pop median | Pop max | |----------|----------|-------------|----------|---------|------------|---------| | Spinlock + deque | 1.584 s | 1.631 s | 1.659 s | 261.05 ms | 268.85 ms | 286.62 ms | | Mutex + deque | 2.591 s | 2.693 s | 2.713 s | 461.52 ms | 477.66 ms | 587.43 ms | | ConcurrentQueue | 267.54 ms | 283.93 ms | 288.31 ms | 47.03 ms | 48.53 ms | 54.17 ms | ## 分析 ### SmallItem (80 bytes) ConcurrentQueue 在 push 和 pop 上均领先锁方案约 50 倍。Spinlock 比 mutex 快约 20% (push) 和 42% (pop)。临界区短时,spinlock 避免了 mutex 在高竞争下的 futex 系统调用开销。 ### LargeItem (4096 bytes) ConcurrentQueue 保持优势 (push 快 ~6x,pop 快 ~6-10x)。Spinlock 仍优于 mutex 约 40%。ConcurrentQueue 的内部预分配块机制避免了逐元素堆分配,而 deque 在高负载下可能触发分配器竞争。 ### 结论 1. **ConcurrentQueue 全面碾压**: 所有场景领先 1-2 个数量级,MPMC 队列场景首选 2. **Spinlock vs Mutex**: 短临界区 + 线程数 <= 核心数时,spinlock 快 20-40% 3. **Spinlock 适用边界**: 线程数远超核心数、临界区含 I/O、需要优先级继承时,应选 mutex ## 参考 - [moodycamel::ConcurrentQueue](https://github.com/cameron314/concurrentqueue) - [C++ atomic_flag](https://en.cppreference.com/w/cpp/atomic/atomic_flag) - [std::mutex](https://en.cppreference.com/w/cpp/thread/mutex)