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

如何在C++中无锁CAS 64位变量的低32位?

问题

我有一个64位共享变量,某线程希望对该变量的低32位执行CAS操作,同时忽略高32位的变化。是否存在可移植的无锁实现方式?另外,如下代码是否可行,是否会违反严格别名规则或C++对象模型?

union {
    std::atomic<uint64_t> desc;
    struct {
        std::atomic<uint32_t> ldesc;
        std::atomic<uint32_t> hdesc;
    };
} variable;

variable.desc = 0;
uint32_t x = 0;
variable.ldesc.compare_exchange_weak(x, 1);
可移植的无锁实现方案

当然有,核心思路是借助完整的64位原子变量来实现低32位的CAS,具体步骤和代码如下:

  • 读取整个64位原子变量的当前值
  • 提取低32位和预期值对比,不匹配则直接返回失败
  • 若匹配,构造新的64位值:保留原高32位,替换低32位为目标值
  • 对整个64位变量执行CAS操作,失败则循环重试
#include <atomic>
#include <cstdint>

std::atomic<uint64_t> shared_var = 0;

bool cas_low_32_bits(uint32_t expected_low, uint32_t desired_low) {
    uint64_t current_full = shared_var.load(std::memory_order_acquire);
    do {
        uint32_t current_low = static_cast<uint32_t>(current_full);
        if (current_low != expected_low) {
            expected_low = current_low;
            return false;
        }
        uint64_t new_full = (current_full & 0xFFFFFFFF00000000ULL) | static_cast<uint64_t>(desired_low);
    } while (!shared_var.compare_exchange_weak(current_full, new_full,
                std::memory_order_release, std::memory_order_acquire));
    return true;
}

这种方案完全遵循C++标准,不依赖任何平台特定逻辑,在所有支持std::atomic<uint64_t>的平台上都能稳定工作。

你给出的代码存在的问题

这段代码属于未定义行为,完全不符合C++标准,具体问题如下:

  • 违反union活跃成员规则:C++标准规定,union同一时间只能有一个活跃成员。你初始化了variable.desc(std::atomic<uint64_t>类型)后,该成员成为活跃成员,此时访问ldesc和hdesc属于访问不活跃的union成员,是标准明确禁止的操作。
  • 违反严格别名规则:std::atomic<uint64_t>与两个std::atomic<uint32_t>是完全不同的类型,通过union重叠存储后交叉访问,会触发严格别名违规,编译器可能生成错误的机器码(比如忽略内存同步、错误优化读写逻辑)。
  • 原子对象布局无保证:std::atomic类型的内部实现依赖平台,标准不保证std::atomic<uint64_t>能拆分为两个独立的std::atomic<uint32_t>。比如部分平台的原子操作需要特定对齐要求,或内部包含同步元数据,这种拆分逻辑根本不成立。

哪怕在某个平台上这段代码碰巧能运行,也不具备可移植性,随时可能因编译器版本、平台变化导致崩溃或逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:12:45