我知道写入volatile
变量会将其从所有cpus的内存中刷新,但是我想知道对volatile变量的读取是否和正常读取一样快?
可volatile
变量永远被放置在CPU缓存或者它总是从主存储器中获取?
我正在制作自己的 C 编译器,以尝试尽可能多地了解有关 C 的详细信息。我现在正在尝试准确地了解volatile
对象是如何工作的。
令人困惑的是,代码中的每个读访问都必须严格执行(C11,6.7.3p7):
具有 volatile 限定类型的对象可能会以实现未知的方式进行修改,或者产生其他未知的副作用。因此,引用此类对象的任何表达式都应严格根据抽象机的规则进行评估,如 5.1.2.3 中所述。此外,在每个序列点,最后存储在对象中的值应与抽象机规定的值一致,除非受到前面提到的未知因素的修改。134)构成对具有易失性限定类型的对象的访问的是实现-定义。
示例:在 中a = volatile_var - volatile_var;
,必须读取 volatile 变量两次,因此编译器无法优化a = 0;
同时,序列点之间的评估顺序未确定(C11,6.5p3):
运算符和操作数的分组由语法指示。除非稍后指定,否则子表达式的副作用和值计算是无序的。
示例:b = (c + d) - (e + f)
未指定计算添加的顺序,因为它们是无序的。
但是,对未排序对象的评估会产生副作用(例如volatile
),行为未定义(C11,6.5p2):
如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是无序的,则行为是未定义的。如果表达式的子表达式有多个允许的排序,并且在任何排序中出现此类未排序的副作用,则行为未定义。
x = volatile_var - (volatile_var + volatile_var)
这是否意味着像未定义这样的表达式?如果发生这种情况,我的编译器应该发出警告吗?
我尝试看看 CLANG 和 GCC 做了什么。既不抛出错误也不发出警告。输出的 asm 显示变量不是按执行顺序读取的,而是从左到右读取的,如下面的 asm risc-v asm 所示:
const int volatile thingy = 0;
int main()
{
int new_thing = thingy - (thingy + thingy);
return …
Run Code Online (Sandbox Code Playgroud) 我想澄清一下,在关系与volatile变量一起工作之前会发生什么.我们有以下变量:
public static int i, iDst, vDst;
public static volatile int v;
Run Code Online (Sandbox Code Playgroud)
和线程A:
i = 1;
v = 2;
Run Code Online (Sandbox Code Playgroud)
和线程B:
vDst = v;
iDst = i;
Run Code Online (Sandbox Code Playgroud)
以下语句是否符合Java内存模型(JMM)?如果没有,那么正确的解释是什么?
i = 1
总是发生在以前 v = 2
v = 2
发生 vDst = v
在JMM 之前,只有它实际发生在时间之前i = 1
发生 iDst = i
在JMM 之前(并且iDst
可以预测分配1
)如果v = 2
实际发生vDst = v
在时间之前i = 1
和之间的顺序iDst …
java volatile java-memory-model thread-synchronization happens-before
有没有办法volatile
在Java中声明数组元素?即
volatile int[] a = new int[10];
Run Code Online (Sandbox Code Playgroud)
声明数组引用 volatile
,但数组元素(例如a[1]
)仍然不是volatile.所以我正在寻找类似的东西
volatile int[] a = new volatile int[10];
Run Code Online (Sandbox Code Playgroud)
但它不会那样工作.有可能吗?
关于我在java中读取volatile关键字的应用,我真的很困惑.
以下陈述是否正确?"在对同一字段的每次后续读取之前发生对易失性字段的写入"
理想情况下应该使用volatile关键字吗?
有什么区别:
class TestClass
{ private int x;
synchronized int get(){return x;}
synchronized void set(int x){this.x = x;}
}
Run Code Online (Sandbox Code Playgroud)和
class TestClass
{ private volatile int x;
int get(){return x;}
void set(int x){this.x = x;}
}
Run Code Online (Sandbox Code Playgroud) 我正在看一个C++类,它有以下几行:
while( x > y );
return x - y;
Run Code Online (Sandbox Code Playgroud)
x
并且y
是类型的成员变量volatile int
.我不明白这个结构.
我在这里找到了代码存根:https://gist.github.com/r-lyeh/cc50bbed16759a99a226.我想这不保证是正确的甚至是工作.
private volatile static Singleton uniqueInstance
Run Code Online (Sandbox Code Playgroud)
在单独使用双锁方法进行同步时,为什么单个实例声明为volatile?我可以在不将其声明为volatile的情况下实现相同的功能吗?
java singleton volatile double-checked-locking thread-synchronization
根据cppreference,volatile
关键字的大多数用法在 C++20 中将被弃用。的缺点是volatile
什么?不使用时的替代解决方案是什么volatile
?
假设我有一个这样的结构:
volatile struct { int foo; int bar; } data;
data.foo = 1;
data.bar = 2;
data.foo = 3;
data.bar = 4;
Run Code Online (Sandbox Code Playgroud)
是否保证所有分配都不会重新排序?
例如,如果没有 volatile,编译器显然可以将它优化为两个不同顺序的指令,如下所示:
data.bar = 4;
data.foo = 3;
Run Code Online (Sandbox Code Playgroud)
但是对于 volatile,是否要求编译器不要做这样的事情?
data.foo = 1;
data.foo = 3;
data.bar = 2;
data.bar = 4;
Run Code Online (Sandbox Code Playgroud)
(将成员视为单独的不相关的易失性实体 - 并进行重新排序,我可以想象它可能会尝试改善引用的局部性,以防foo和bar位于页面边界 - 例如。)
此外,答案是否与 C 和 C++ 标准的当前版本一致?
volatile ×10
java ×5
c++ ×4
c ×2
concurrency ×2
arrays ×1
c++20 ×1
c11 ×1
casting ×1
performance ×1
singleton ×1
while-loop ×1