如果跨线程共享变量,将变量标记为volatile是否有用?

时间:2015-03-17 19:20:50

标签: c++ multithreading c++11 volatile

  

注意!

     

我显然没有向这里的每个人清楚地表达我的观点,这令人非常沮丧。我的目标是打消volatile实际上是无操作的神话,它什么都不做。我并没有试图说它应该被使用,它是必不可少的,它不是多余的等等。

     

我已经证明volatile仍然做了一件事。我承认在某些情况下它是多余的,并且多线程示例是一个糟糕的选择。

     

我也没有试图隐瞒我的答案的初始修订包含错误这一事实。但是这个Q& A甚至没有达到其预期目的。为此,我认为是时候把它扔掉了。

     

感谢Kerrek和T.C.为了他们的见解。我只是不认为他们的回答符合我想问的问题。我很确定这是我的错误。

     

因此我放弃它!并将其作为问题的副本而不是它的意图,但它被解释为。

     

干杯! (& hth。)

我正在写一个线程中的变量并在另一个线程中读取它。我被告知,volatile对此完全无用,除非我正在使用硬件,否则我不需要在这个时代使用它。

int x = 0;
void thread1()
{
   while (true) {
      sleep(1);
      if (x > 0)
         break;
   }
}

void thread2()
{
   while (true) {
      sleep(1);
      x++;
   }
}

在这种情况下,使用volatile可以获得任何收益吗? 如果x不是简单的int而是类类型呢?

那该怎么办?

1 个答案:

答案 0 :(得分:20)

您被正确告知,volatile对于线程间通信没有用。不要为此目的使用它。它不提供同步,并为您的代码留下数据争用。相反,在正确同步对共享状态的访问时,您不需要volatile

“你是什么意思”的正确代码使用原子变量进行共享状态或使用互斥锁保护共享状态,并且所有线程都会正确地观察共享状态。例如:

#include <atomic>

std::atomic<int> x = 0;

void thread1()
{
   while (true) {
      sleep(1);
      if (x > 0)
         break;
   }
}

void thread2()
{
   while (true) {
      sleep(1);
      x++;
   }
}

任何时候都不需要volatile

请注意,volatile在线程中可能很有用,可以强制执行一个没有副作用的循环:

// Spend some time
for (volatile int i = 0; i != LARGE_NUMBER; ++i)
{ /* do nothing */ }

// or even:
for (int i = 0; const_cast<volatile int &>(i) != LARGE_NUMBER; ++i) {}