InterlockedExchange()和线程安全

时间:2014-06-25 06:24:24

标签: c++ windows multithreading

volatile LONG g_lRunning = 1;

bool IsRunningEx()
{
   return ::InterlockedExchange(&g_lRunning, 1) == 1;
}

bool IsRunning()
{
   return g_lRunning == 1;
}

void Close()
{
   ::InterlockedExchange(&g_lRunning, FALSE);
}

void f1()
{
   while (IsRunning())
   {
      // do some thing
   }
}

void f2()
{
   Close();
}

int _tmain(int argc, _TCHAR* argv[])
{
   std::thread t1(f1);
   std::thread t2(f2);
   t1.detach();
   t2.detach();

   return 0;
}

void f1_()
{
   while (IsRunningEx())
   {
     // do some thing
   }

   ::InterlockedExchange(&g_lRunning, FALSE); 
   // I must do some thing like this in here or in IsRunningEx internal, 
   // because after calling IsRunningEx() g_lRunning will be TRUE. 
   // So when call IsRunningEx() next time, it will return TURE, 
   // but it would return FALSE in hope.
}  
  1. 线程安全,在g_lRunning中直接阅读IsRunning()并在g_lRunning代码中使用InterlockedExchange撰写Close()吗?

  2. 如果我将f1替换为f1_,我会遇到问题,就像f1_中的评论一样,你有什么更好的想法(不要在c中使用atom) ++ 11)

2 个答案:

答案 0 :(得分:1)

关于问题1:
据我了解,直接读取g_lRunning是安全的。写入必须是原子的,因此对于每个写入操作都有一个InterlockedXXX函数,但读取不需要是原子的,只有读取没有InterlockedXXX函数。

在谈论线程安全时,您需要记住volatile不保证获取/释放语义,但在您的情况下,这应该不是问题。

关于问题2:
您也可以使用return ::InterlockedCompareExchange(&g_lRunning, 0, 0) == 1。你可以用你喜欢的任何值替换两个零。

如果您可以使用C ++ 11,我建议您使用新的std::atomic

答案 1 :(得分:0)

看起来你正在创建一个SimpleSpinLock,所以值得注意的是,当你在while循环中运行时,你正在旋转并浪费CPU周期。如果您打算长时间旋转,内核模式锁定可能会更有效。