当前位置: 首页 > 知识库问答 >
问题:

C++volatile关键字引入了内存栅栏吗?

百里渊
2023-03-14

我理解volatile通知编译器值可能会被更改,但是为了完成这个功能,编译器是否需要引入一个内存栅栏来使其工作呢?

从我的理解来看,对易失性对象的操作顺序是不能重新排序的,必须保留。这似乎暗示了一些记忆栅栏是必要的,实际上没有办法绕过这一点。我这样说对吗?

在这个相关的问题上有一个有趣的讨论

乔纳森·韦克利写道:

...对不同volatile变量的访问不能由编译器重新排序,只要它们出现在单独的完整表达式中...没错volatile对于线程安全是无用的,但不是因为他给出的原因。这不是因为编译器可能会重新排序对volatile对象的访问,而是因为CPU可能会重新排序。原子操作和内存障碍阻止编译器和CPU重新排序

这会产生两个问题:它们中的任何一个是“正确的”吗?实际的实现到底是做什么的?

共有1个答案

韦胜泫
2023-03-14

不是解释volatile是做什么的,而是让我解释一下什么时候应该使用volatile

  • 在信号处理程序内部时。因为编写volatile变量几乎是标准允许您从信号处理程序中执行的唯一操作。从C++11开始,您就可以使用std::atomator来实现这一目的,但前提是原子是无锁的。
  • 根据Intel处理setjmp时。
  • 直接处理硬件时,您希望确保编译器不会优化您的读写操作。

例如:

volatile int *foo = some_memory_mapped_device;
while (*foo)
    ; // wait until *foo turns false

在所有其他情况下,volatile的使用都应该被认为是不可移植的,并且不再通过代码审查,除非是在处理C++11之前的编译器和编译器扩展时(例如MSVC的/volatile:ms开关,它在X86/I64下默认启用)。

 类似资料:
  • 一、Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的。 Java内存模型规定了所有的变量都存储在主内存中。每条线程中还有自己的工作内存,线程的工作内存中保存了被该线程所使用到的变量(这些变量是从主内存中拷贝而来)。线程对变量的所有操作(读取,赋值)都必须在工作内存中进行。不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通

  • 我知道关于volatile有很多问题,但我只是被讨论搞糊涂了:Java:volatile如何保证这段代码中“数据”的可见性? 我读过的每个网站都说可以在缓存中存储一个变量(使这个值对于其他线程不可见),我甚至发现了这个例子https://dzone.com/articles/java-volatile-keyword-0 所以我的第一个问题是:Java是否在缓存中存储变量值(在哪个缓存中?l1 l

  • 问题内容: 今天的工作中,我遇到了volatileJava中的关键字。不太熟悉,我发现了以下解释: Java理论与实践:管理波动 鉴于该文章详细解释了所讨论的关键字,您是否曾经使用过它,或者是否曾经遇到过可以正确使用此关键字的情况? 问题答案: volatile具有内存可见性的语义。基本上,字段的值对所有读取器(尤其是其他线程)在写入操作完成后变为可见。没有,读者可能会看到一些未更新的值。 回答你

  • Joe Albahari有一个很棒的多线程系列,这是必读的,任何做C#多线程的人都应该熟记于心。 然而,在第4部分中,他提到了volatile的问题: 请注意,应用volatile并不能阻止先写后读的交换,这可能会产生脑筋急转弯。Joe Duffy用下面的例子很好地说明了这个问题:如果Test1和Test2同时在不同的线程上运行,那么a和b的值都可能为0(尽管在x和y上都使用volatile) 然

  • 本文向大家介绍Java中的volatile关键字,包括了Java中的volatile关键字的使用技巧和注意事项,需要的朋友参考一下 volatile修饰符用于让JVM知道访问该变量的线程必须始终将其自身的变量私有副本与内存中的主副本合并。 访问易失性变量将同步所有在主存储器中缓存的变量副本。可变变量只能应用于对象类型或私有类型的实例变量。易失性对象引用可以为null。 示例

  • 问题内容: 今天的工作中,我遇到了volatileJava中的关键字。不太熟悉,我找到了这种解释。 鉴于该文章详细解释了所讨论的关键字,您是否曾经使用过它,或者是否曾见过可以正确使用此关键字的情况? 问题答案: volatile具有内存可见性的语义。基本上,volatile字段的值对所有读取器(尤其是其他线程)可见,在该字段上完成写操作之后。没有volatile,读者可能会看到一些未更新的值。 要