我有兩個線程,生產者和消費者。數據交換由兩個指針的std ::原子公司內部控制:如何強制std :: atomic在其他std :: atomic被寫入後被讀取?
std::atomic<TNode*> next = nullptr;
std::atomic<TNode*> waiting = nullptr;
螺紋生產者出臺所準備的數據和事後檢查等待的值:
TNode* newNext = new TNode();
// ... fill *newNext ...
next.store(newNext, std::memory_order_release);
TNode* oldWaiting = waiting.load(std::memory_order_seq_cst);
if(oldWaiting == nullptr)
{
/* wake up Consumer */
}
它是crucical負載在waiting
之後來到next
,但std::memory_order_seq_cst
的店鋪比我真正需要更強的保證,因爲我真的只需要這兩個訪問固定的順序。 是否有可能在不需要memory_order_seq_cst
的情況下獲得我需要的內存順序?
下面是圖片的其餘部分:
螺紋消費者檢查next
。如果它發現它爲空,它會設置waiting
在阻塞自身之前發信號給Producer。
TNode* newCurrent = next.load(std::memory_order_consume);
if(newCurrent == nullptr)
{
waiting.store(current, std::memory_order_relaxed);
/* wait, blocking, for next != nullptr */
}
current = newCurrent;
整個事情是一個生產者 - 消費者隊列,在不需要所有複雜機制的情況下保持低鎖定的需要。 next
實際上是一個單鏈表的當前節點。數據通常以突發形式出現,因此在大多數情況下,消費者會發現大量節點已準備好用於消費;除了極少數情況外,兩個線程都只在突發之間經過一次鎖定和阻塞/喚醒。
據我所知'memory_order_acquire'只限制其他讀取在加載之前被重新排序,但不會限制寫入,也不會阻止它在加載後移動讀取。或者我錯了? –
延遲加載最容易理解。編譯器總是可以延遲其他負載(假設它們本身沒有被排序)。如果另一個線程正在向負載被延遲的變量寫入新值,這種延遲只能給出不同的結果,這意味着無論如何你都有競爭條件。記憶順序在存在這種未定義行爲時沒有意義。我不認爲隨機寫入會受到傷害,因爲寫入被另一個線程拾取,用於計算,然後用於通過獲取語義來影響負載的計算。然後你有一個依賴。 – MSalters