CppCoreGuidelines CP.8 不要通过 volatile 进行同步处理
22 June 2023
“Don’t try to use volatile
for synchronization”
理由
与其他语言不同,在 C++ 中, volatile
不提供原子性操作能力。不能在线程之间同步,不能防止编译器或硬件对指令重排序引起的问题。简单说,就是
volatile
不提供任何并行运算支持。
坏例子
int free_slots = max_slots; // current source of memory for objects Pool* use() { if (int n = free_slots--) return &pool[n]; }
这里,我们遇到一个问题:在单线程环境下,这段代码没有任何问题。但是如果多个线程执行这段代码,就会在 free_slots
这个变量上出现数据竞争情况。两个线程可能从 free_slots
得到一样的数值。所以,熟悉其他编程语言的人,可能会通过以下方法解决这个问题:
volatile int free_slots = max_slots; // current source of memory for objects Pool* use() { if (int n = free_slots--) return &pool[n]; }
然而,这样做并不能达到同步的效果:数据竞争仍然存在!
C++ 提供的机制是 atomic
类型:
atomic<int> free_slots = max_slots; // current source of memory for objects Pool* use() { if (int n = free_slots--) return &pool[n]; }
现在,这个操作是原子操作,而非分步骤的:读取-自减-写入,不然在操作过程中,其他线程可能在其中插入进行操作。
其他情况
在复杂的例子中可以使用 mutex