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

为何用std::atomic实现单次执行会出现多次执行问题?

问题:std::atomic实现的单次执行逻辑为何在多线程下失效?

我用以下代码实现某段逻辑仅执行一次:

class Test {
public:
    void foo() {
        if (m_barrier.exchange(true)) {
            return;
        }

        // This should only execute once
    }
private:
    std::atomic<bool> m_barrier { false };
};

多线程会多次调用foo()函数,预期exchange下方的代码每个对象实例仅执行一次。我原本认为这段代码是正确的,但发现有时该代码会执行多次。

运行环境为Android的aarch64架构CPU,已在三款不同手机上复现问题。不确定是Android标准库的bug,还是我的代码本身无法保证单次执行?

补充说明:

  • 请勿建议使用std::once,因某些原因无法采用。
  • 我知道可以用std::mutex搭配非atomic bool替代,我的问题是为何std::atomic实现不具备线程安全性?

分析与解答

你的代码逻辑本身从C++标准层面是正确的:std::atomic::exchange是原子操作,会原子性地将值替换为true并返回旧值。理论上,只有第一个调用foo()的线程会得到旧值false,进入后续逻辑;其他线程得到旧值true,直接返回。

但在Android aarch64平台出现多次执行的情况,大概率是Android标准库的atomic实现存在问题,或者是平台特定的内存模型行为未被正确处理:

  • 内存顺序问题:默认情况下exchange使用的是std::memory_order_seq_cst,这是最严格的内存顺序,保证所有线程看到的操作顺序一致。但如果Android的libc++实现对aarch64的atomic操作做了不符合标准的优化,比如偷偷降低了内存顺序,可能导致线程间的操作可见性出现问题。
  • 硬件指令生成问题:aarch64的原子交换依赖ldxr/stxr这样的独占加载/存储指令序列,若标准库的实现没有正确生成这些指令,或者存在指令重排序漏洞,可能导致多个线程同时进入临界区。
  • 对象实例重复创建:如果存在多个Test对象实例,每个实例的m_barrier是独立的,自然会各自执行一次逻辑——这不属于atomic的问题,需要排查对象创建逻辑。

总结:你的代码逻辑符合C++线程安全规范,问题大概率出在Android aarch64平台的标准库atomic实现上,而非代码本身的设计错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:33:14