有一位C++委员会语言进化主席做了一个很好的演讲来解释为什么。
简要概述,从中删除volatile
的地方在标准中没有明确定义的含义,只会引起混乱。
+=
是单个/原子指令吗?++
呢?compare_exchange
需要多少次读/写操作?如果失败怎么办?void foo(int volatile n)
或int volatile foo()
是什么意思?*vp;
是否应该进行加载?(这在标准中已更改两次。)在C和C++中,人们过去通常使用volatile
来实现线程安全。在C++11中,新增了一些非UB的方法来创建线程之间的同步和共享状态。我建议阅读Back to Basics: Concurrency作为一个很好的入门指南。
std::atomic
不检查线程是否启用;然而,这并不是滥用volatile
进行线程处理的理由。volatile
是/曾经用于描述硬件何时可以与程序交互,并且只有禁用优化器的效果,这不是它的预期含义。如果在单线程环境中优化atomic
是一个严重的问题,我会要求编译器实现这个功能。但是,我也会想知道为什么您在单线程代码中使用同步特性。 - unDeadHerbsgcc -Wa,-momit-lock-prefix=yes
来编译使用std::atomic
的单线程代码。这只是通过传递-momit-lock-prefix=yes
选项使汇编器忽略lock
前缀;它不会让编译器将事物优化到寄存器中,但是add [mem],1
只是一个普通的内存目标增量,而不是原子RMW(也不是内存屏障)。这意味着您不必滥用volatile
作为atomic<T>
的单线程版本,我认为这就是您在现代C ++中提到volatile与多线程有关的原因。 - Peter Cordes
volatile
的用法并没有被弃用,因为它们很有用(例如在直接从指定内存位置加载或存储的代码中使用,比如在设备驱动程序中)。相当多的“弃用用法”与使用特性的能力有关,而太多的程序员错误地将其作为使变量访问变得原子化的手段。C++库现在(自C++11以来)提供了一种正确的方式来确保变量的原子访问,因此,在意图进行原子访问时不合适地使用volatile
是不明智的,应该予以避免。 - Peter