不要再误解C volatile了
时间:2021-09-14 11:32:15
[导读]作者:LiamHuang最近在讨论多线程编程中的一个可能的falsesharing问题时,有人提出加volatile可能可以解决问题。这种错误的认识荼毒多年,促使我写下这篇文章。约定Volatile这个话题,涉及到计算机科学多个领域多个层次的诸多细节。仅靠一篇博客,很难穷尽这些细...
最近在讨论多线程编程中的一个可能的 false sharing 问题时,有人提出加 volatile 可能可以解决问题。这种错误的认识荼毒多年,促使我写下这篇文章。
约定
含义
单词 volatile 的含义
A situation that is volatile is likely to change suddenly and unexpectedly.这里对 volatile 的解释有三个精髓的形容词和副词,体现了 volatile 的含义。
程序中 volatile 的含义
此处说的「读取内存」,包括了读取 CPU 缓存和读取计算机主存。然而,由于 MMIP(Memory mapped I/O)的存在,这个假设不一定是真的。例如说,假设 p 指向的内存是一个硬件设备。这样一来,从 p 指向的内存读取数据可能伴随着可观测的副作用:硬件状态的修改。此时,代码的原意可能是将硬件设备返回的连续两个 int 分别保存在 a 和 b 当中。这种情况下,编译器的优化就会导致程序行为不符合预期了。
关键字 volatile 的含义
C 语言:Every access (both read and write) made through an lvalue expression of volatile-qualified type is considered an observable side effect for the purpose of optimization and is evaluated strictly according to the rules of the abstract machine (that is, all writes are completed at some time before the next sequence point). This means that within a single thread of execution, a volatile access cannot be optimized out or reordered relative to another visible side effect that is separated by a sequence point from the volatile access.这里首先解释两组概念:值类型和序列点(执行序列)。
C 语言:Every access (read or write operation, member function call, etc.) made through a glvalue expression of volatile-qualified type is treated as a visible side-effect for the purposes of optimization (that is, within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution, see std::memory_order). Any attempt to refer to a volatile object through a non-volatile glvalue (e.g. through a reference or pointer to non-volatile type) results in undefined behavior.
volatile 与多线程





