2014-09-02 58 views
1
#include <iostream> 
#include <atomic> 
#include <array> 
#include <thread> 

template <typename T> 
struct node { 
    T  value; 
    node* next{nullptr}; 
}; 

typedef node<int> node_type; 

std::atomic<node_type*> _begin; 

node_type* get() { 
    node_type* b = _begin; 

    while (!_begin.compare_exchange_weak(b, b->next)) 
     ; 

    return b; 
} 

void give(node_type* v) { 
    v->next = _begin; 

    while (!_begin.compare_exchange_weak(v->next, v)) 
     ; 
} 

void get_and_give() { 
    for (int i = 0; i < 1000000; ++i) { 
     auto n = get(); 

     give(n); 
    } 
} 

int main(int argc, const char * argv[]) 
{ 
    std::array<node_type, 4> _nodes; 

    for (auto & i : _nodes) 
     give(&i); 

    std::thread t1(get_and_give); 
    std::thread t2(get_and_give); 
    std::thread t3(get_and_give); 

    get_and_give(); 

    t1.join(); 
    t2.join(); 
    t3.join(); 

    return 0; 
} 

在get返回的值的下一個指針內有一個競賽(我相信)。這不會發生在2個運行get_and_give的線程上,所以它看起來像是在其他線程中缺乏順序一致性,但我所做的一切都是memory_order_seq_cst,所以我不明白這可能是一個問題?比賽在哪裏?

任何想法!?

回答

3

我懷疑你遇到了什麼被稱爲ABA問題。

wikipedia

ABA問題同步期間發生時,當被讀兩次的位置,具有相同的值兩者讀取和「值是相同的」是用來表示「沒有任何改變」 。然而,另一個線程可以在兩次讀取之間執行並更改值,執行其他工作,然後將值更改回來,從而欺騙第一個線程思考「沒有任何變化」,即使第二個線程的工作違反了該假設。

+0

在維基百科的例子幾乎是我的確切代碼,所以這可能是它! – pat 2014-09-02 16:45:57