如何在32位系统上无临界区实现64位变量的原子自增
解决32位系统上64位变量原子自增的无临界区方案
这确实是32位系统处理64位原子操作的典型痛点——硬件原生只支持4字节的无锁原子操作,所以编译器会自动 fallback 到基于软件锁的实现,也就出现了你看到的性能警告。如果不想用显式临界区(比如mutex这类),可以试试下面几种更高效的方案:
1. 手动拆分64位变量为两个32位原子变量
把64位计数器拆分为高位和低位两个32位原子变量,手动处理进位逻辑,完全依赖原生32位原子操作实现无锁自增:
#include <stdatomic.h> #include <stdint.h> atomic_uint32_t tick_counter_low = ATOMIC_VAR_INIT(0); atomic_uint32_t tick_counter_high = ATOMIC_VAR_INIT(0); void atomic_inc_system_tick() { uint32_t old_low = atomic_fetch_add_explicit(&tick_counter_low, 1, memory_order_relaxed); // 低位从最大值溢出到0时,给高位加1 if (old_low == UINT32_MAX) { atomic_fetch_add_explicit(&tick_counter_high, 1, memory_order_release); } } // 读取完整64位值时,要确保高低位状态一致 uint64_t get_system_tick() { uint32_t high, low; do { high = atomic_load_explicit(&tick_counter_high, memory_order_acquire); low = atomic_load_explicit(&tick_counter_low, memory_order_relaxed); // 循环检查高位是否变化,避免读到中间状态 } while (atomic_load_explicit(&tick_counter_high, memory_order_acquire) != high); return ((uint64_t)high << 32) | low; }
这种方案完全基于标准C原子操作,移植性强,性能和原生32位原子操作接近,唯一的额外开销是进位检查和读取时的循环验证。
2. 利用平台/编译器内置的64位原子函数
如果你的目标平台是x86 32位系统,GCC/Clang提供了内置函数__sync_fetch_and_add_8,它会生成硬件支持的lock cmpxchg8b指令——这是x86硬件原生支持的64位原子操作,比软件锁的性能好很多:
#include <stdint.h> uint64_t system_tick_counter_us = 0; void atomic_inc_system_tick() { __sync_fetch_and_add(&system_tick_counter_us, 1); }
注意:这是编译器特定的扩展,移植性不如标准原子操作,但胜在实现简单、性能比CAS循环好。
3. 用标准CAS操作模拟原子自增
利用C标准库的atomic_compare_exchange_weak做循环CAS,这是跨平台的无锁实现方式:
#include <stdatomic.h> #include <stdint.h> atomic_uint64_t system_tick_counter_us = ATOMIC_VAR_INIT(0); void atomic_inc_system_tick() { uint64_t old_val = atomic_load_explicit(&system_tick_counter_us, memory_order_relaxed); // 循环尝试CAS,直到成功 while (!atomic_compare_exchange_weak_explicit( &system_tick_counter_us, &old_val, old_val + 1, memory_order_release, memory_order_relaxed )) { // 失败后更新old_val,继续重试 } }
这种方案的优势是完全符合C标准,移植性极佳;缺点是在高并发场景下可能会有较多的CAS重试,性能略低于硬件原生的原子操作,但依然比软件临界区高效。
以上三种方案都不需要显式的临界区锁,而是通过硬件原子特性或无锁算法实现了64位变量的原子自增,你可以根据自己的移植性需求和并发场景选择合适的方案。
内容的提问来源于stack exchange,提问作者Priyank Pandya
相关产品推荐
相关产品推荐

