gpt4 book ai didi

c++ - 在这种情况下, volatile 限定词重要吗?

转载 作者:太空狗 更新时间:2023-10-29 21:21:48 25 4
gpt4 key购买 nike

我在问题C++ volatile member functions的答案中看到了一个代码示例,演示了volatile限定词的用法,引用如下:

volatile int x;

int DoSomething() {
x = 1;
DoSomeOtherStuff();
return x+1; // Don't just return 2 because we stored a 1 in x.
// Check to get its current value
}

我不知道 volatile限定符是否对上述代码有任何影响。 x是一个全局变量,在对 x进行写入和读取之间有一个函数调用,我们只读取一次 x。编译器是否应该对 x进行真正的读取(即使不是 volatile)?

我认为这与以下情况不同:
volatile int x;

int DoSomething() {
x = 1;
while (x != 1)
break;
}

在这种情况下,我们在写入 x之后立即重复读取 x,因此 volatile对于获取由其他线程编写的 x的最新值是必需的。

我对这些代码示例的理解不是很自信,如果我错了,请纠正我。

编辑(回复评论):对不起,我没有清楚说明我的问题。至于第一个代码段,我在质疑该代码是否是 volatile可能用法(不是volatile的 保证用法)的有效示例。我只是想知道,如果没有 volatile,那么假设没有多线程或内存映射IO之类的其他非琐事,是否可以保证 x中对 DoSomeOtherStuff()的任何可能更改都可以反射(reflect)在 return x+1中。因为如果保证没有 volatile就可以工作,那么该示例就显得无关紧要,更不用说一些注释指出的 volatile的平台相关性质了。但是,如果不能保证,那么恐怕我现有的某些代码可能无法按预期工作。
(我可能根本不应该放第二个代码段。)

最佳答案

volatile限定词从不改变含义
代码本身。除非编译器可以证明DoSomeOtherStuff()不会修改x,它必须重新读取x不管是volatile还是否。为了使volatile相关,x必须类似于内存映射的IO,
可能会在程序外部更改。如果我们想像是
每微秒递增的寄存器,例如:

int
MeasureExecutionTime()
{
x = 0;
DoSomeOtherStuff();
return x;
}

将返回 DoSomeOtherStuff中使用的时间;的
即使内联,也需要编译器重新加载它 DoSomeOtherStuff,并看到它从未修改 x

当然,在典型的台式机上,可能没有
任何内存映射的IO,如果有的话,它在 protected 内存中,
无法访问的地方。而且很多编译器并没有真正
生成必要的代码以使其正常运行。
因此,对于此类机器上的通用应用程序,
每次使用 volatile确实没有任何意义。

编辑:

关于您的第二个代码段:通常实现的是, volatile不保证您获得的最新副本 x。可以说,这不符合 volatile,但这是g++,Sun CC和至少某些方式
VC++版本工作。编译器将发出负载
每次在循环中读取 x的指令,但是硬件
可能会在管道中找到该值,并且不会传播
读取请求到内存总线。为了保证
重新读取后,编译器将不得不插入篱笆或
腹部指导。

也许更重要的是(因为迟早会
发生,以便值不会在管道中),此循环
该机制将用于等待,直到其他值写入
其他线程已稳定。除了挥发物没有
影响何时发生其他变量的读写。

要了解 volatile,了解
引入目的。引入时
内存管道等未知,以及(C)标准
被忽略的线程(或具有共享内存的多个进程)。 volatile的目的是允许支持内存映射
IO,写地址有外部后果,并且
连续读取并不总是读取相同的内容。有
绝不希望代码中的其他变量是
已同步。在线程之间通信时,通常
读取和写入所有共享变量的顺序,其中
很重要如果我做类似的事情:
globalPointer = new Xxx;

和其他线程可以访问 globalPointer,这很重要 Xxx的构造函数中的所有写入都变为
更改 globalPointer的值之前可见
发生。为此,不仅 globalPointer具有
成为 volatile,还包括 Xxx的所有成员,以及任何
可能使用的 Xxx成员函数的变量,或任何数据
可通过 Xxx中的指针访问。这根本不是
合理;您很快就会在其中拥有一切
程序 volatile。即使这样,它也需要
编译器正确实现 volatile,设置围栏或
每次访问均应提供相关的说明。 (FWIW:围栏或
孟巴指令可以增加存储时间
的访问权限是10或更多。)

这里的解决方案不是不稳定的,而是可以访问
指针(并且仅访问该指针)原子,使用 atomic_loadatomic_store原语已添加到C++ 11。
这些原语确实会导致必要的围栏或腰部
使用说明;他们还告诉编译器不要动
它们之间的任何内存访问。这样就可以使用 atomic_load在上面设置指针,将导致所有先前的内存写入
在写入指针之前对其他线程可见
变得可见(在读取线程使用的情况下 atomic_read,当然- atomic_write确保所有
以前的写在所有
线程和 atomic_read确保所有后续读取
将进入“普通”内存,而不是获取一些值(value)
已经在准备中)。

关于c++ - 在这种情况下, volatile 限定词重要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21887594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com