【问题标题】:Volatile member variable [duplicate]易失性成员变量[重复]
【发布时间】:2018-08-09 09:28:33
【问题描述】:

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

问题一:

如果在一个类函数中设置成员变量并在另一个类函数中轮询 - 是否需要 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”的场景(某种优化)?

【问题讨论】:

  • 对于您的情况,有 std::atomic。
  • 您需要一个minimal reproducible example 来说明“同时没有2 个线程”的意思
  • 如果行为由于某些优化而改变,您将导致未定义的行为。所以你真正应该问的是,这是明确定义的
  • volatile 在 C++ 中是一个被极度误解的关键字。我已经关闭了“重复链”的开始,因为他们应该向您解释这一切。不过,赞成这个问题:它很好地呈现和有用。
  • 看看这个讨论 atomic 和 volatile 之间区别的问题:stackoverflow.com/questions/8819095/…

标签: c++ c++11 volatile


【解决方案1】:

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

不需要volatile

是否存在调用FuncB后FuncA不打印“hello”的场景(某种优化)?

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

更多详情请见CPU Cache Flushing Fallacy

【讨论】:

    【解决方案2】:

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

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

    不同的线程正在访问 MyClass,

    不!只会访问对象,而不是类!

    但不能同时有 2 个线程,

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

    对你来说,你必须使用带有 std::mutex 的锁函数或使用 std::atomic 变量。在这种情况下,Volatile 根本没有帮助!

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2011-06-17
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 2013-07-27
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      相关资源
      最近更新 更多