繁体   English   中英

C ++线程安全-在工作者和控制器之间交换数据

[英]C++ thread safety - exchange data between worker and controller

我对该主题仍然感到不安全,希望大家能帮助我-

为了在轮询某些内容的工作线程与对最新数据感兴趣的控制线程之间传递数据(配置或结果),我最终或多或少地重复使用了以下模式:

Mutex m;
tData * stage;       // temporary, accessed concurrently

// send data, gives up ownership, receives old stage if any
tData * Send(tData * newData)
{
   ScopedLock lock(m);
   swap(newData, stage);              
   return newData;
}

// receiving thread fetches latest data here
tData * Fetch(tData * prev)
{
  ScopedLock lock(m);
  if (stage != 0)
  {
     // ... release prev
     prev = stage;
     stage = 0;
  }
  return prev;  // now current
}

注意:这不应该是完整的生产者-消费者队列,只有msot最近数据是相关的。 另外,我在这里略略了资源管理。

必要时,我使用两个这样的阶段:一个将配置更改发送给工作程序,以及将结果发送回。

现在,我的问题

假设ScopedLock实现了完整的内存屏障:

  • 阶段和/或workerData是否需要可变?
  • tData成员需要volatile吗?
  • 我可以使用智能指针代替原始指针吗?比如boost::shared_ptr
  • 还有什么可能出错吗?
  • 我基本上是在尝试避免“易受感染”传播到tData中,并最小化锁争用(似乎也可以实现无锁实现)。 但是,我不确定这是否是最简单的解决方案。

ScopedLock充当完整的内存屏障。 由于所有这些都或多或少地依赖于平台,因此可以说Visual C ++ x86或x64,尽管也欢迎其他平台的差异/说明。


(对“ Intel TBB”之类的库的推荐,表示“感谢”,我想在这里理解平台问题)

您不需要在这里volatile 仅当值可能由于程序外部的原因而发生更改(例如,变量代表内存映射的硬件寄存器)时才使用volatile 此处的值仅在程序内部进行修改,因此您可以信任编译器知道何时以及何时不能缓存值。

如果您需要确保工作者和控制器不会同时访问共享数据,则建议您使用互斥锁 在您的SendFetch功能中,只需锁定互斥锁,操作stage并释放互斥锁即可。 我不知道是什么系统库您有可用,但有POSIX互斥体(从并行线程)的一个很好的描述在这里 Win32版本(尽管解释较少)可在此处获得 其他库将使用不同的名称,但是概念是相同的。

好吧,这是一个问题:

您的send函数需要通过引用(或指向指针的指针)传递newData。 否则,交换的结果将永远不会返回给调用者。

您不需要volatile就意味着每次访问数据时总是从内存中读取数据。 由于您的程序总是在更改stage的值,因此编译器将知道发生了什么,一切都会很好。 仅当程序外有其他值更改时,才使用volatile。 例如,您有一个串行端口正在将数据发送到内存中的某个位置,并且您的程序正在轮询该内存以​​进行更新。 每次轮询该内存时,都必须检查内存,而不是缓存,这就是使用volatile的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM