2014-06-30 100 views
6

我在閱讀安東尼威廉姆斯的C++ Concurrency in Action,並且不瞭解其執行lock_free_stack類的push類。C++ 11鎖定免費堆棧

爲什麼地球上原子load不在while循環中?他給出的理由是:

因此,您不必每次都通過循環, 重新加載頭,因爲編譯器會爲您做到這一點。

但我不明白。有人可以對此有所瞭解嗎?

template<typename T> 
class lock_free_stack 
{ 
private: 
struct node 
{ 
    T data; 
    node* next; 
    node(T const& data_) : 
    data(data_) 
    {} 
}; 
std::atomic<node*> head; 
public: 
void push(T const& data) 
{ 
    node* const new_node=new node(data); 
    new_node->next=head.load(); 
    while(!head.compare_exchange_weak(new_node->next,new_node)); 
} 
}; 

回答

6

關鍵是在compare_exchange_weak的接口,在這種情況下接受2個參數。第一個是對期望值的參考,第二個是期望值。如果原子的當前值不等於預期輸入,則它將返回false,並將預期輸入設置爲當前值。

所以在這種情況下,它在做什麼是設置new_node->next = head。然後,它說如果head仍等於new_node->next,則將其換成head。如果它不再是該值,則使用對new_node->next的引用爲其分配當前值head。由於循環的每次迭代失敗也會將new_node->next替換爲當前值head,因此沒有讀取可以在循環體中複製。

+0

是的,它現在非常有意義。謝謝! – Stringer

3

compare_exchange_weak文檔:

原子方式存儲在*這與 預期值的值進行比較,並且如果這些是相等的,取代了以前的具有期望 (執行讀 - 修改 - 寫操作)。否則,將* this中存儲的實際值加載到預期值(執行加載操作)。

正如你看到的,否則head實際值被裝入的預期。