我正在使用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将无法打印"你好"?
答案 0 :(得分:0)
如果成员变量在一个类函数中设置并在另一个类函数中轮询 - 是否需要volatile?
无需volatile
。
是否有一种情况(某种优化)在FuncB被调用之后,FuncA将无法打印"你好"?
当CPU对内存进行存储时,存储首先进入存储缓冲区。在存储缓冲区中,其他线程在将存储提交到缓存/内存之前不会看到存储的效果。
有关详细信息,请参阅CPU Cache Flushing Fallacy。
答案 1 :(得分:0)
如果成员变量在一个类函数中设置并在另一个类函数中轮询 - 是否需要volatile?
哪种方法更改变量并不重要。只有哪个线程正在访问访问变量的方法才是这里的重点!
不同的线程正在访问MyClass,
没有!只访问对象,而不是类!
但同时没有2个主题,
这也是错误的假设! 编译器仍然需要知道从不同的上下文/线程访问变量。如果编译器不知道来自不同线程的访问,则允许进行所有类型的优化和缓存的szenarios,例如将事物保存在寄存器中或不同步的cpu缓存等等。不同的线程可以在不同的cpu内核上运行,并且它们可以具有与其他线程不同步的不同缓存。因此,您必须告诉编译器有来自不同线程的访问权限。在内部,编译器会为同步数据访问生成内存屏障。
对于您来说,您必须使用std :: mutex的锁定函数或使用std :: atomic vars。挥发性在这种情况下根本无济于事!