调用__sync_fetch_and_add(&value, 0)仅用于读取是否有意义?
__sync_fetch_and_add(&value, 0) 用作原子读取的意义 你观察得没错,__sync_fetch_and_add(&value, 0) 确实是在读取value的值,但它和普通的value读取在多线程/多核环境下有本质区别,这么做是有明确意义的:
1. 强制内存可见性,避免缓存旧值
x86处理器上,对齐的32位int普通读取本身是原子的,但普通读取不保证内存可见性。CPU的缓存机制可能会让当前核读取到缓存里的旧值,而看不到其他核/线程对value的最新修改。
__sync_fetch_and_add作为GCC的内置原子操作,会隐含内存屏障语义(acquire语义),强制从主存读取最新的value值,确保能立刻看到其他线程的修改。
2. 阻止编译器优化
编译器在优化代码时,可能会把普通的value读取缓存到寄存器里。比如在一个循环中多次读取value,编译器可能只执行一次内存读取,后续直接用寄存器里的值,不会再去内存同步最新状态。
而__sync_fetch_and_add是原子操作,编译器不会对它做这类缓存优化,每次调用都会实际去内存读取value的当前值。
3. 明确代码语义
这个写法相当于给其他开发者传递明确信号:这里的读取需要保证线程安全的可见性,不是普通的局部变量读取。避免后续维护时有人误改成普通读取,引入线程安全隐患。
补充:x86的原子性误区
你提到“即使无锁,一个线程在另一个线程执行__sync_fetch_and_add()过程中读取值也不会有问题”——这里的“没问题”指的是原子性(不会读到半修改的中间值),但不代表能读到最新值。普通读取的原子性是x86硬件保证的,但可见性需要通过原子操作或内存屏障来保证。
内容的提问来源于stack exchange,提问作者some user
相关产品推荐
相关产品推荐

