问题标签 [volatile]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 不稳定的保证和乱序执行
重要编辑我知道两个分配发生的线程中的“之前发生”我的问题是另一个线程是否有可能在“a”仍然为空时读取“b”非空。所以我知道,如果你从与之前调用setBothNonNull(...)的线程相同的线程调用doIt() ,那么它不能抛出 NullPointerException。但是,如果从另一个线程调用doIt()而不是调用setBothNonNull(...)怎么办?
请注意,此问题仅与volatile
关键字和volatile
保证有关:与关键字无关(因此请不要synchronized
回答“您必须使用同步”,因为我没有任何问题要解决:我只是想了解volatile
保证(或缺乏保证)关于乱序执行)。
假设我们有一个包含两个volatile
String 引用的对象,这些引用由构造函数初始化为 null,并且我们只有一种方法来修改这两个 String:通过调用setBoth(...)并且我们只能在之后将它们的引用设置为非空引用(仅允许构造函数将它们设置为空)。
例如(这只是一个例子,还没有问题):
在setBothNoNull(...)中,分配非空参数“a”的行出现在分配非空参数“b”的行之前。
然后,如果我这样做(再一次,毫无疑问,接下来是问题):
我的理解是否正确,由于无序执行我可以获得NullPointerException?
换句话说:不能保证因为我读到了一个非空的“b”,我就会读到一个非空的“a”?
因为由于无序(多)处理器和工作方式volatile
“b”可以在“a”之前分配?
volatile
保证在写入之后读取始终会看到最后写入的值,但是这里有一个无序的“问题”,对吗?(再一次,“问题”是故意试图理解volatile
关键字和 Java 内存模型的语义,而不是解决问题)。
c++ - C++ 中的 volatile 与 mutable
我对 volatile 和 mutable 之间的区别有疑问。我注意到这两者都意味着它可以改变。还有什么?它们是一样的吗?有什么不同?它们适用于什么地方?为什么提出这两个想法?如何以不同的方式使用它们?
非常感谢。
c++ - C ++中易失性成员函数的目的是什么?
volatile
C ++中成员函数的目的是什么?
c# - Interlocked 是否保证对 C# 中其他线程的可见性,还是我仍然必须使用 volatile?
我一直在阅读类似问题的答案,但我仍然有点困惑......亚伯有一个很好的答案,但这是我不确定的部分:
...声明一个变量 volatile 使其在每次访问时都是 volatile 的。不可能以任何其他方式强制这种行为,因此 volatile 不能用 Interlocked 代替。这在其他库、接口或硬件可以访问您的变量并随时更新它或需要最新版本的情况下是必需的。
是否Interlocked
保证原子操作对所有线程的可见性,还是我仍然必须volatile
在值上使用关键字以保证更改的可见性?
这是我的例子:
更新:
我是一项糟糕的运动,我改变了原来的例子,所以又是这样:
c++ - 为什么 C++ 中会寄生“易失性”?
考虑以下代码:
这给出了一个错误g++
:
我的意图是我想让它变得p
不稳定。但是,一旦我读取了 的值p
,我就不关心访问v
是否是易失性的。为什么需要v
声明为 volatile?
这当然是假设的代码。在实际情况下,您可以想象它p
指向一个内存位置,但在外部进行了修改,我想v
指向当时指向的位置p
,v = p
即使后来p
被外部修改。因此p
是易变的,但v
不是。
顺便说一句,我对这被认为是 C 和 C++ 的行为感兴趣,但在 C 中这只会产生警告,而不是错误。
c++ - 为什么在 std::atomic 中使用 volatile 限定符?
根据我从Herb Sutter和其他人那里读到的内容,您会认为volatile
并发编程是完全正交的概念,至少就 C/C++ 而言。
但是,在 GCC实现中,所有std::atomic
的成员函数都有volatile
限定符。Anthony Williams的std::atomic
.
那么有什么关系,我的atomic<>
变量是否需要volatile
?
c++ - 为什么 volatile 在多线程 C 或 C++ 编程中没有用?
正如我最近发布的这个答案volatile
所示,我似乎对多线程编程上下文中的实用程序(或缺乏实用程序)感到困惑。
我的理解是:任何时候一个变量可能在一段代码访问它的控制流之外被改变,这个变量应该被声明为volatile
. 信号处理程序、I/O 寄存器和被另一个线程修改的变量都构成了这种情况。
因此,如果您有一个全局 int foo
,并且foo
由一个线程读取并由另一个线程以原子方式设置(可能使用适当的机器指令),则读取线程看到这种情况的方式与看到由信号处理程序调整的变量或由外部硬件条件修改,因此foo
应该声明volatile
(或者,对于多线程情况,使用内存隔离负载访问,这可能是一个更好的解决方案)。
我怎么错了?
c++ - volatile 可能是用户定义的类型,以帮助编写线程安全的代码
我知道,之前在几个问题/答案中已经很清楚了,这volatile
与 c++ 内存模型的可见状态有关,而不是与多线程有关。
另一方面,Alexandrescu 的这篇文章volatile
不是将关键字用作运行时功能,而是用作编译时检查,以强制编译器无法接受可能不是线程安全的代码。在文章中,关键字的使用更像是一个required_thread_safety
标签,而不是volatile
.
这是(ab)使用volatile
适当的吗?该方法中可能隐藏了哪些可能的陷阱?
首先想到的是增加了混乱:volatile
与线程安全无关,但由于缺乏更好的工具,我可以接受它。
文章的基本简化:
如果声明一个变量volatile
,则只能volatile
调用它的成员方法,所以编译器会阻塞调用其他方法的代码。std::vector
将实例声明为volatile
将阻止该类的所有使用。添加一个锁定指针形状的包装器来执行const_cast
释放volatile
需求,任何通过锁定指针的访问都将被允许。
从文章中窃取:
笔记
在出现前几个答案之后,我想我必须澄清一下,因为我可能没有使用最合适的词。
的使用volatile
不是因为它在运行时提供了什么,而是因为它在编译时意味着什么。也就是说,const
如果关键字在用户定义的类型中很少使用,则可以使用相同的技巧volatile
。也就是说,有一个关键字(恰好拼写为 volatile)允许我阻止成员函数调用,而 Alexandrescu 正在使用它来欺骗编译器,使其无法编译线程不安全的代码。
我认为它存在许多元编程技巧,这些技巧不是因为它们在编译时做了什么,而是因为它迫使编译器为你做些什么。
c++ - 为什么 std::cout 将 volatile 指针转换为 bool?
如果您尝试 cout 指向 volatile 类型的指针,甚至是您通常期望 cout 打印字符串的 volatile char 指针,您将改为简单地得到 '1' (假设指针不为 null 我认为)。我假设输出流 operator<< 是专门用于 volatile 指针的模板,但我的问题是,为什么?什么用例激发了这种行为?
示例代码:
输出:
c - 为什么 gcc 不删除对非易失性变量的检查?
这个问题主要是学术性的。我是出于好奇而问的,并不是因为这对我构成了实际问题。
考虑以下不正确的 C 程序。
这个程序是不正确的,因为处理程序中断了程序流程,所以running
可以随时修改,因此应该声明volatile
。但是假设程序员忘记了这一点。
带有标志的 gcc 4.3.3-O3
将循环体(在对running
标志进行一次初始检查后)编译为无限循环
这是意料之中的。
while
现在我们在循环中放入一些微不足道的东西,比如:
突然间,gcc 不再优化循环条件了!循环体的组件现在看起来像这样(再次在 处-O3
):
我们看到running
每次循环都会从内存中重新加载;它甚至没有缓存在寄存器中。显然 gcc 现在认为 的值running
可能已经改变。
那么为什么 gcc 突然决定需要重新检查running
这种情况下的值呢?