据我了解,C volatile
和内存asm的内联asm已用于在内存映射I / O之上实现设备驱动程序。在Linux内核中可以找到几个例子。
如果我们忘记了未捕获异常的风险(如果有的话),用C ++ 11原子替换它们是否有意义?或者,它有可能吗?
答案 0 :(得分:2)
据我所知,读取引用std::atomic
旨在管理对内存的多线程访问(并发等)。但据我所知,正如你所说,volatile
是为内存映射I / O和信号处理等内容而设计的。因此,volatile
对原子访问没有影响,如果单独使用,则不能解决像原子一样的多线程访问问题。反之亦然 - 原子不提供volatile
的特征。
因此,对你的问题的简短回答是否定的。
答案 1 :(得分:2)
通常,您可以使用原子替换内存栅栏,但不能替换volatile
,除非它与栅栏一起用于线程间通信。
关于内存映射I / O,原子不够的原因是:
volatile
保证您对程序中该变量的所有内存访问都会确实发生,并且它们恰好按照您指定的顺序发生(在单个线程中)。 std::atomic
只保证您的程序就好像所有这些内存访问一样(根据C ++的内存模型,它不知道关于内存映射I / O)和 - 取决于指定的内存排序 - ,好像它们按指定的顺序发生。实际上,这意味着编译器可以例如用一次写入替换对相同(非易失性)原子的连续写入(如果之间没有其他同步),对于读取也是如此。如果不使用读取的结果,它甚至可以完全消除读取(编译器可能仍然必须发出内存屏障)。
在更理论的层面上,如果您的编译器可以证明您的所有程序都返回42,则允许将其转换为单个指令,而与程序在此过程中使用的线程数和原子数无关。如果你的程序使用不是这种情况的volatile变量。
编辑:例如This paper显示了允许编译器应用于原子循环变量的一些可能的(可能是意外的)优化。