挥发性变量被优化? [英] volatile variable being optimized away?

查看:254
本文介绍了挥发性变量被优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个后台线程循环的状态变量 done 。当我想停止线程时,我将变量 done 设置为 true 。但显然这个变量从来没有设置。我理解编译器可能会优化它,所以我已标记完成 volatile 。但这似乎没有任何效果。注意,我不担心竞争条件,所以我没有使它 atomic 或使用任何同步结构。我如何让线程不跳过测试的变量在每次迭代?还是完全是其他问题? done 最初为 false

I have a background thread which loops on a state variable done. When I want to stop the thread I set the variable done to true. But apparently this variable is never set. I understand that the compiler might optimize it away so I have marked done volatile. But that seems not to have any effect. Note, I am not worried about race conditions so I have not made it atomic or used any synchronization constructs. How do I get the thread to not skip testing the variable at every iteration? Or is the problem something else entirely? done is initially false.

struct SomeObject
{
    volatile bool done_;
    void DoRun();
};

static void RunLoop(void* arg)
{
   if (!arg)
      return;

   SomeObject* thiz = static_cast<SomeObject*>(arg);
   while( !(thiz->done_) ) {
      thiz->DoRun();
   }
   return;
}


推荐答案

volatile 在C ++中没有任何多线程的意义。它是C的延期,用作 sig_atomic_t 的修饰符,用于处理信号处理程序和访问内存映射设备。没有语言强制的强制C ++函数重新访问内存,这导致竞争条件(读者永远不会打扰检查两次作为优化),其他人上面注意到。

volatile doesn't have any multi-threaded meaning in C++. It is a holdover from C, used as a modifier for sig_atomic_t flags touched by signal handlers and for access to memory mapped devices. There is no language-mandated compulsion for a C++ function to re-access memory, which leads to the race condition (reader never bothering to check twice as an "optimization") that others note above.

使用 std :: atomic (从C ++ 11或更高版本)。

Use std::atomic (from C++11 or newer).

它可以,通常是无锁的:

It can be, and usually is lock-free:

struct SomeObject {
  std::atomic_bool done_;
  void DoRun();
  bool IsDone() { return done_.load(); }
  void KillMe() { done_.store(true); }
};

static void RunLoop(void *arg) {
  SomeObject &t = static_cast<SomeObject &>(*arg);

  cout << t.done_.is_lock_free(); // some archaic platforms may be false

  while (!t.IsDone()) {
    t.DoRun();
  }
}

load / code>和 store()方法强制编译器至少在每次迭代时检查内存位置。对于 x86 [_64] SomeObject 实例的 done _ 成员将被本地缓存和检查,没有锁,甚至是原子/锁定的内存读取。如果你正在做一个比单向标志设置更复杂的事情,你需要考虑使用像显式记忆围栏等。

The load() and store() methods force the compiler to, at the least, check the memory location at every iteration. For x86[_64], the cache line for the SomeObject instance's done_ member will be cached and checked locally with no lock or even atomic/locked memory reads as-is. If you were doing something more complicated than a one-way flag set, you'd need to consider using something like explicit memory fences, etc.

C ++ 11没有多线程内存模型,因此您必须依赖具有特殊编译器权限的第三方库(如pthreads)或使用特定于编译器的功能来获得等效的。

这篇关于挥发性变量被优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆