据我所知,在内存映射I/O之上实现设备驱动程序时,使用了C volatile和可选的内存围栏内联asm。在Linux内核中可以找到几个例子。
如果我们忘记了潜在异常的风险(如果有的话),用C++11原子替换它们是否有意义?或者,有可能吗?
发布于 2016-02-24 07:14:55
通常,您可以用atomics替换内存栅栏,但不能使用volatile,除非它与专门用于线程间通信的栅栏一起使用。
关于内存映射I/O,atomics不足够的原因是:
volatile保证您程序中对该变量的所有内存访问实际上都会发生,并且它们的发生(在单个线程中)完全按照您指定的顺序进行。std::atomic只保证您的程序会表现为,就好像所有的内存访问都会发生一样(根据C++的内存模型,它不知道内存映射的I/O),并且--取决于指定的内存顺序--就好像按指定的顺序发生一样。实际上,这意味着编译器可以用单个写替换对同一个(非易失性的)原子的连续写入(如果之间没有其他同步),对于读也是如此。如果没有使用读取的结果,它甚至可以完全消除读取(编译器可能仍然需要发出内存屏障)。
在更理论的层面上,如果您的编译器能够证明您的程序所做的全部是返回42,那么它可以将其转换为一个指令,而不依赖于您的程序在这个过程中使用了多少线程和atomics。如果您的程序使用易失性变量,则情况并非如此。
编辑:例如,本论文显示了一些可拥有的(可能是意想不到的)优化,编译器允许应用于原子循环变量。
发布于 2016-02-24 06:03:13
正如我所理解的,std::atomic用于管理对内存的多线程访问(并发等)。但是我知道,正如您所说的,volatile是为诸如内存映射I/O和信号处理之类的事情设计的。因此,如果单独使用volatile,则不会影响原子访问,也不会解决诸如atomics之类的多线程访问问题。反之亦然-- atomics不提供volatile的特性。
因此,对你问题的简短回答是否定的。
https://stackoverflow.com/questions/35594009
复制相似问题