2013-11-24 26 views
2

在一些論壇和書籍(即 C++併發行動)還有多生產者/多消費者堆的一個很好的例子,在流行實現他們通常做到以下幾點:爲什麼std :: atomic <T> :: compare_exchange_ *不應該遭受ABA問題?


// head is an std::atomic<node*> variable 
node *old_head = head.load(); 
while(old_head && !head.compare_exchange_weak(old_head, old_head->next)); 
... 
爲什麼要使用 STD :: atomic <T> :: compare_exchange_ *防止ABA問題?
假設:

  • old_head->未來解決之前的線程是捷足先登(之前 compare_exchange_weak
  • 那麼BA情景剛好
  • 線程後恢復頭== old_head有效;在這種情況下 old_head->未來不會再解決,指向一個無效的內存位置
  • compare_exchange_weak將被執行,會通過,但價值 old_head->未來仍然會

然後會發生ABA相關問題。

我相信我錯過了一些東西。我在這裏錯過了什麼?

乾杯

回答

2

是的,你會患上ABA問題。

雖然我認爲這並不重要,因爲你所指的實現(在CiA中列出7.3)無論如何都是無效的,它會泄漏節點。

如果我們看看最簡單的參考計數實現,使用無鎖std::shared_ptr(在CiA中列出7.9)的實現,我們發現問題不會發生。當使用共享指針時,old_head不會被刪除,因爲我們的線程仍然持有對它的引用,因爲這樣一個新創建的頭不能在舊頭的內存地址中創建。

在官方Concurrency in Action Manning forums上也有關於堆棧實現中的ABA問題的線程。

+0

Darn,我知道這個實現泄漏了什麼,但是在本章結尾處有一段文字說明本章中的例子不會受到ABA問題的影響。我無言以對,他們應該更加小心......我已經浪費了數小時的時間試圖找出爲什麼我看錯了ABA問題,但我是對的......老實說,我對本書的作者有點失望,評論者(如果有的話)。 – Emanuele

相關問題