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

为何std::atomic<int>++性能远慢于std::mutex保护的int++?

原子变量与互斥锁保护普通变量的性能对比问题

测试程序

为对比std::atomic<int>++与std::mutex保护的int++性能差异,编写了如下测试代码:

#include <iostream>
#include <atomic>
#include <mutex>
#include <thread>
#include <chrono>
#include <limits>
using namespace std;
#ifndef INT_MAX
const int INT_MAX = numeric_limits<std::int32_t>::max();
const int INT_MIN = numeric_limits<std::int32_t>::min();
#endif
using std::chrono::steady_clock;
const size_t LOOP_COUNT = 12500000;
const size_t THREAD_COUNT = 8;
int intArray[2] = { 0, INT_MAX };
atomic<int> atomicArray[2];
void atomic_tf() {//3.19s
    for (size_t i = 0; i < LOOP_COUNT; ++i) {
        atomicArray[0]++;
        atomicArray[1]--;
    }
}
mutex m;
void mutex_tf() {//0.25s
    m.lock();
    for (size_t i = 0; i < LOOP_COUNT; ++i) {
        intArray[0]++;
        intArray[1]--;
    }
    m.unlock();
}
int main() {
    {
        atomicArray[0] = 0;
        atomicArray[1] = INT_MAX;
        thread tp[THREAD_COUNT];
        steady_clock::time_point t1 = steady_clock::now();
        for (size_t t = 0; t < THREAD_COUNT; ++t) {
            tp[t] = thread(atomic_tf);
        }
        for (size_t t = 0; t < THREAD_COUNT; ++t) {
            tp[t].join();
        }
        steady_clock::time_point t2 = steady_clock::now();
        cout << (float)((t2 - t1).count()) / 1000000000 << endl;
    }
    {
        thread tp[THREAD_COUNT];
        steady_clock::time_point t1 = steady_clock::now();
        for (size_t t = 0; t < THREAD_COUNT; ++t) {
            tp[t] = thread(mutex_tf);
        }
        for (size_t t = 0; t < THREAD_COUNT; ++t) {
            tp[t].join();
        }
        steady_clock::time_point t2 = steady_clock::now();
        cout << (float)((t2 - t1).count()) / 1000000000 << endl;
    }
    return 0;
}

测试结果

在Windows和Linux平台(分别使用clang14、g12编译)多次运行,结果一致:

  • atomic_tf函数执行耗时3秒以上
  • mutex_tf函数执行耗时0.25秒以上
    两者性能差距近10倍。

问题与解答

测试程序是否能说明原子变量开销远大于互斥锁+普通变量?

不能直接得出这个结论,该测试是极端高竞争的批量操作场景,不代表所有使用场景。如果是单次或低频率的并发操作,原子变量通常比互斥锁更高效——因为互斥锁涉及内核态切换的开销,而原子变量多数情况下是用户态的无锁操作。

性能差异的成因

  1. 锁竞争次数的本质差异

    • mutex_tf中,每个线程仅在进入时做一次锁竞争,拿到锁后所有循环内的++/--都是普通内存操作,完全无并发竞争,操作直接在本地缓存完成,速度极快。
    • atomic_tf中,循环内的每一次++/--都是原子操作,每次都要和其他7个线程竞争缓存一致性:CPU需要通过MESI协议同步多个核心的缓存状态,每次原子操作都要经历“缓存失效-获取最新值-修改-同步回缓存”的过程,这个开销会随竞争线程数增加急剧放大。
  2. 操作优化空间的差异

    • 互斥锁锁定后,线程对普通变量的操作是无同步要求的单线程操作,编译器能做循环展开、寄存器缓存变量等激进优化。
    • 原子变量的操作强制要求内存可见性和原子性,编译器无法对这类操作做优化,且每次操作都要触发缓存同步的硬件开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:35:25