volatile是一种在C / C ++中使单个字节成为primefaces的正确方法吗?

我知道volatile不会在int上强制执行primefaces性,但是如果你访问单个字节会这样做吗? 如果我没记错的话,语义要求写入和读取始终来自内存。

或者换句话说:CPU是否始终以primefaces方式读写字节?

标准不仅没有说明primefaces性,而且甚至可能会提出错误的问题。

CPU通常以primefaces方式读取和写入单个字节。 问题出现的原因是,当您有多个内核时,并非所有内核都会将该字节视为同时写入。 实际上,在所有内核看到写入之前,可能需要相当长的时间(在CPU中说,数千或数百万条指令(也就是微秒或可能是毫秒))。

所以,你需要一些有点错误的C ++ 0xprimefaces操作。 他们使用CPU指令确保事物的顺序不会搞砸,并且当其他内核查看您编写后写入的值时,他们会看到新值,而不是旧值。 他们的工作不仅仅是操作的primefaces性,而是确保适当的同步步骤也会发生。

该标准没有提到primefaces性。

volatile关键字用于指示变量( intchar或其他)可以从外部不可预测的源中获得值。 这通常会阻止编译器优化变量。

对于primefaces,您需要检查编译器的文档以查看它是否提供任何帮助或声明或pragma。

在任何理智的cpu上,读取和写入任何对齐的,字大小或更小的类型都是primefaces的。 这不是问题。 问题是:

  • 仅仅因为读取和写入是primefaces的,所以读取/修改/写入序列不是primefaces的。 在C语言中, x++在概念上是读/修改/写周期。 您无法控制编译器是否生成primefaces增量,并且通常不会。
  • 缓存同步问题。 在中间废话架构(几乎任何非x86),硬件太愚蠢,以确保每个CPU看到的内存视图反映了写入发生的顺序。 例如,如果cpu 0写入地址A然后写入B,则cpu 1可能会在地址B处看到更新,但不会在地址A处看到更新。您需要特殊的内存fence / barrier操作码来解决此问题,并且编译器不会生成他们适合你。

第二点仅在SMP /多核系统上很重要,所以如果你很高兴将自己限制在单核,那么你可以忽略它,然后在任何理智的cpu架构上, 简单的读写都将在C中是primefaces的。 但是你不能用它做很多有用的事情。 (例如,以这种方式实现简单锁定的唯一方法是O(n)空间,其中n是线程数。)

简短回答 :不要使用volatile来保证primefaces性。

很长的答案人们可能会认为,由于CPU在单个指令中处理单词,因此简单的单词操作本质上是线程安全的。 使用volatile的想法是确保编译器不对共享变量中包含的值做出假设。

在现代多处理器机器上,这种假设是错误的。 鉴于不同的处理器内核通常会有自己的缓存,可能会出现重新排序对主内存的读写操作并且代码最终无法按预期运行的情况。

因此,在线程之间共享访问内存时, 始终使用锁,例如互斥锁或关键部分。 当没有争用时(通常不需要进行系统调用),它们会出乎意料地便宜,并且它们会做正确的事情。

通常,它们将通过调用数据存储器屏障(ARM上的DMB)指令来防止乱序读取和写入,该指令保证读取和写入以正确的顺序发生。 在这里查看更多细节。

volatile的另一个问题是它会阻止编译器进行优化,即使完全没问题也是如此。