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

std::memory_order_seq_cst全局单序机制解析及ARM64平台异常结果问询

std::memory_order_seq_cst全局单序机制解析及ARM64平台异常结果问询

最近在ARM64架构的Mac上跑一段C++原子变量测试代码,结果遇到了和预期不符的情况,想请教一下各位大佬问题出在哪。

测试背景与预期

我的测试逻辑很直接:有两个独立的std::atomic<int>变量x和y,初始值都是0,之后会被分别设置为1;同时启动多个读取线程,每个线程读取x和y的当前值。

根据C++标准中std::memory_order_seq_cst的**全局单序(single global order)**语义,理论上不应该同时出现{x=0,y=1}和{x=1,y=0}这两种结果——因为全局单序要求所有seq_cst操作都遵循一个统一的全局顺序:要么x=1的写入先于y=1,要么反过来,这样所有线程看到的结果应该保持一致,不会同时出现这种交叉的情况。

为了同步所有线程的启动时机,我用了std::atomic<bool> ready作为触发信号:所有线程必须等ready被设为true后才开始执行读写操作。而且所有原子操作我都指定了std::memory_order_seq_cst内存序,按道理应该严格遵循全局单序才对,但在我的ARM64 Mac上,确实出现了这两种交叉结果同时存在的情况。

测试代码

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

const char *machine() {
    std::cout << "Compiled on/for: ";
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
    return "x86-64 (64-bit Intel/AMD)";
#elif defined(__i386__) || defined(_M_IX86)
    return "x86 (32-bit Intel/AMD)";
#elif defined(__aarch64__) || defined(_M_ARM64)
    return "ARM64 (AArch64)";
#elif defined(__arm__) || defined(_M_ARM)
    return "ARM (32-bit)";
#elif defined(__powerpc__) || defined(__powerpc64__) || defined(_M_PPC)
    return "PowerPC";
#else
    return "Unknown architecture";
#endif
}

static constexpr std::size_t ITERATIONS = 1000000;
static constexpr std::size_t NUM_THREADS = 10;

using result = std::pair<int, int>;
std::vector<result> results;
std::atomic_bool ready;
std::atomic<int> x, y;

void initialize() {
    results.clear();
    results.resize(NUM_THREADS, {0, 0});
    ready.store(false, std::memory_order_seq_cst);
    x.store(0, std::memory_order_seq_cst);
    y.store(0, std::memory_order_seq_cst);
}

void modify_x() {
    while (!ready.load(std::memory_order_seq_cst)) ;
    x.store(1, std::memory_order_seq_cst);
}

void modify_y() {
    while (!ready.load(std::memory_order_seq_cst)) ;
    y.store(1, std::memory_order_seq_cst);
}

void check(int i) {
    while (!ready.load(std::memory_order_seq_cst)) ;
    int xl = x.load(std::memory_order_seq_cst);
    int yl = y.load(std::memory_order_seq_cst);
    results[i] = {xl, yl};
}

bool check_results() {
    // 统计四种结果的出现次数:{0,0}, {0,1}, {1,0}, {1,1}
    int arr[4] = {0, 0, 0, 0};
    for (const auto &res : results) {
        if (res.first == 0 && res.second == 0)
            arr[0]++;
        else if (res.first == 0 && res.second == 1)
            arr[1]++;
        else if (res.first == 1 && res.second == 0)
            arr[2]++;
        else if (res.first == 1 && res.second == 1)
            arr[3]++;
    }
    bool failure = arr[1] != 0 && arr[2] != 0;
    if (failure)
        std::cout << "Results: {0, 0}: " << arr[0] << ", {0, 1}: " << arr[1] 
                  << ", {1, 0}: " << arr[2] << ", {1, 1}: " << arr[3] 
                  << " failure = " << failure << "\n";
    return failure;
}

bool iterate(std::size_t iter) {
    initialize();
    std::vector<std::jthread> threads_;
    threads_.reserve(NUM_THREADS + 2);

    for (std::size_t i = 0; i < NUM_THREADS; ++i)
        threads_.emplace_back(check, i);
    threads_.emplace_back(modify_y);
    threads_.emplace_back(modify_x);

    ready.store(1, std::memory_order_seq_cst);

    for (auto &t : threads_)
        t.join();

    return check_results();
}

int main() {
    std::cout << "Compiled on/for: " << machine() << "\n";
    std::cout << "Testing sequential consistency semantics\n";

    std::size_t total_failures = 0;
    for (std::size_t i = 0; i < ITERATIONS; ++i)
        total_failures += iterate(i);

    std::cout << "Total failed iterations: " << total_failures << " out of " << ITERATIONS << "\n";
    return 0;
}

编译运行命令及输出

我用以下命令编译并运行程序:

g++ rough2.cpp -std=c++20 -o prog && ./prog

输出结果(截取关键部分):

Compiled on/for: Compiled on/for: ARM64 (AArch64)
Testing sequential consistency semantics
Results: {0, 0}: 4, {0, 1}: 1, {1, 0}: 1, {1, 1}: 4 failure = 1
Results: {0, 0}: 4, {0, 1}: 1, {1, 0}: 1, {1, 1}: 4 failure = 1
Results: {0, 0}: 5, {0, 1}: 1, {1, 0}: 1, {1, 1}: 3 failure = 1
...
Total failed iterations: 15 out of 1000000

核心疑问

按我对std::memory_order_seq_cst全局单序的理解,所有seq_cst操作应该遵循一个统一的全局顺序,那为什么在ARM64平台上会出现这种交叉结果呢?是我对全局单序的理解有误,还是ARM64的硬件/编译器实现有特殊逻辑?亦或是我的测试代码里存在没注意到的漏洞?

麻烦各位大佬帮忙分析一下,谢谢啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 11:40:29