易失性成员的访问方法
我们有一个代表原子整数的包装器。在内部,它是使用 Windows 的 InterlockedIncrement()
和 InterlockedDecrement()
函数实现的,这些函数作用于 volatile long
变量:
class AtomicInt {
public:
...
operator long() const { return m_value; }
private:
volatile long m_value;
};
我的问题是,上述用于查询当前值的运算符是否正确(即您总是获得当前值),或者我是否需要将该方法也声明为 易失性
以防止缓存值出现任何问题?
We have a wrapper that represents an atomic integer. Internally, it is implemented using Windows' InterlockedIncrement()
and InterlockedDecrement()
functions, which work on a volatile long
variable:
class AtomicInt {
public:
...
operator long() const { return m_value; }
private:
volatile long m_value;
};
My question is, is the above operator for querying the current value correct (i.e. you always get the current value) or do I need to declare the method also as volatile
to prevent any problems with cached values?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你所做的很好......你不需要将该方法标记为易失性。此外,由于您已在类声明中包含了方法的定义,因此该方法通常会由编译器隐式内联,因此在编译器优化过程中将忽略实际的函数调用机制。因此,在大多数情况下,变量本身将被直接访问,而无需中间函数调用,这使得变量上的
易失性
声明就足够了。顺便说一句,为了供将来参考,请记住,在 x86 之外的多处理器环境中,
volatile
关键字不足以确保使用共享内存值的线程不会接收缓存数据。一般来说,易失性
关键字仅仅阻止某些编译器优化。但在内存一致性规则较弱的处理器平台(即 ARM、PowerPC 等)上,即使变量被标记为易失性,您仍然可以最终从本地处理器核心访问缓存值。解决这个问题的方法是实现适当的内存屏障,以确保实际处理器内存缓存中的任何陈旧值都被刷新和刷新。这些当然是依赖于平台的指令......您的情况的好消息是您使用的编译器内在函数将确保您的AtomicInt
类不会遇到这些问题,但我做到了想让您了解围绕volatile
关键字的普遍问题。What you've done is fine ... you don't need to mark the method as volatile. Also since you've included the definition of the method in the class declaration, the method will typically be implicitly inlined by the compiler, so the actual function call mechanism would be elided during the compiler optimization process. Thus in most contexts, the variable itself would be accessed directly without an intervening function call, making the
volatile
declaration on the variable enough.BTW, for future reference, keep in mind that in a multi-processor environment outside of x86, the
volatile
keyword is not enough to ensure that a thread using your shared memory value not receive cached data. Thevolatile
keyword in general merely prevents certain compiler optimizations. On processor platforms with weaker memory consistency rules (i.e., ARM, PowerPC, etc.) though, you can still end up accessing a cached value from the local processor core even if the variable is marked as volatile. The way around this is to implement the proper memory barriers to make sure that any stale values in the actual processor memory caches are flushed and refreshed. These are of course platform-dependent instructions ... the good news in your case is the compiler intrinsics you're using will assure that your don't face these issues with yourAtomicInt
class, but I did want to make you aware of this general issue surrounding thevolatile
keyword.使
m_value
变得不稳定就足够了。这足以阻止访问方法被优化掉。It is enough to make
m_value
volatile. That is enough to stop the access method being optimised away.