易变成员变量[重复]

问题描述 投票:3回答:2

这个问题在这里已有答案:

我正在使用C ++ 11,我遇到了一个带有volatile成员变量的类,这引发了一个问题:

问题1:

如果一个成员变量在一个类函数中设置并在另一个类函数中轮询 - 是否需要volatile?如果是的话,何时? (我知道如果x映射到硬件寄存器,我们应该使用volatile,我的意思是“纯软件”场景)

例:

class MyClass
{
public:
    FuncA { if (x==5) print("hello"); }
    FuncB { x=5;}
private:
    volatile int x = 0;
}

不同的线程正在访问MyClass实例,但同时没有2个线程,所以不需要保护x。

问题2:

是否存在一种情况(某种优化),在调用FuncB之后,FuncA将不会打印“hello”?

c++ c++11 volatile
2个回答
0
投票

如果一个成员变量在一个类函数中设置并在另一个类函数中轮询 - 是否需要volatile?

不需要volatile

是否存在一种情况(某种优化),在调用FuncB之后,FuncA将不会打印“hello”?

当CPU对内存进行存储时,存储首先进入存储缓冲区。在存储缓冲区中,在将存储提交到缓存/内存之前,其他线程将看不到存储的效果。

有关详细信息,请参阅CPU Cache Flushing Fallacy


0
投票

如果一个成员变量在一个类函数中设置并在另一个类函数中轮询 - 是否需要volatile?

哪种方法更改变量并不重要。只有哪个线程访问访问变量的方法才是这里的重点!

不同的线程正在访问MyClass,

没有!只访问对象,而不是类!

但同时没有2个线程,

这也是错误的假设!编译器仍然需要知道从不同的上下文/线程访问变量。如果编译器不知道来自不同线程的访问,则允许进行所有类型的优化和缓存的szenarios,例如将事物保存在寄存器中或不同步的cpu缓存等等。不同的线程可以在不同的cpu内核上运行,并且它们可以具有与其他线程不同步的不同缓存。因此,您必须告诉编译器有来自不同线程的访问权限。在内部,编译器为同步数据访问生成内存屏障。

对于您,您必须使用std :: mutex的锁定函数或使用std :: atomic vars。在这种情况下,易失性无济于事!

© www.soinside.com 2019 - 2024. All rights reserved.