易变成员变量

时间:2018-03-01 10:25:00

标签: c++ c++11 volatile

我正在使用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将无法打印"你好"?

2 个答案:

答案 0 :(得分:0)

  

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

无需volatile

  

是否有一种情况(某种优化)在FuncB被调用之后,FuncA将无法打印"你好"?

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

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

答案 1 :(得分:0)

  

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

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

  

不同的线程正在访问MyClass,

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

  

但同时没有2个主题,

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

对于您来说,您必须使用std :: mutex的锁定函数或使用std :: atomic vars。挥发性在这种情况下根本无济于事!