簡體   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