2012-06-11 95 views
3

我有一個多線程應用程序(使用std :: thread)和一個管理器(類樹),它在不同的子樹上執行某段代碼(嵌入式結構子樹)在平行下。基本思想是每個SubTree實例都有一個存儲對象的雙端隊列。如果雙端隊列爲空,則線程將等待,直到在雙端隊列中插入新元素或達到終止條件。一個子樹可以生成對象並將它們推送到另一個子樹的雙端隊列中。爲了方便起見,我所有的std :: mutex,std :: locks和std :: variable_condition都存儲在一個名爲「locks」的結構中。C++在調用std :: unique_lock之前解鎖std :: mutex等待

類樹創建運行下面的方法(第一次嘗試)某些線程:

void Tree::launch(SubTree & st, Locks & locks) 
{ 
/* some code */ 

std::lock_guard<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st 
if (st.deque_.empty()) // check that the deque is still empty 
{ 
    // some threads are still running, wait for them to terminate 

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ; 
    locks.restart_condition_[st.id_].wait(wait_lock) ; 
} 

/* some code */ 
} 

的問題是,當線程正在等待「deque_lock」仍處於鎖定狀態。因此,沒有對象可以被併發的對象添加到當前線程的雙端隊列中。

所以我把lock_guard成unique_lock和管理的手動鎖定/解鎖:

void launch(SubTree & st, Locks & locks) 
{ 
/* some code */ 

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st 
if (st.deque_.empty())   // check that the deque is still empty 
{ 
    deque_lock.unlock() ; // unlock the access to the deque to enable the other threads to add objects 

    // DATA RACE : nothing must happen to the unprotected deque here !!!!!! 

    // some threads are still running, wait for them to terminate 

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ; 
    locks.restart_condition_[st.id_].wait(wait_lock) ; 
} 

/* some code */ 
} 

現在的問題,是有數據的比賽,我想,以確保「等待「指令直接在」deque_lock.unlock()「之後執行。有誰會知道用標準庫創建這樣一個關鍵指令序列的方法嗎?

在此先感謝。

回答

0

這是一個很好的做法不承擔,當您從等待條件變量返回,你等待條件滿足

我寧願寫代碼:

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]); 
while(st.deque_.empty()) 
{ 
    deque_lock.unlock(); 
    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]); 
    locks.restart_condition_[st.id_].wait(wait_lock); 
    deque_lock.lock(); 
} 

此代碼保證,那一段時間後,你的隊列不爲空。 std::condition_variable::wait甚至可以用一個謂詞來模擬這個行爲之王(但是,由於隊列鎖定,它不能在這裏使用)。

+0

感謝您的快速回答和建議,我會在我的代碼中考慮到這一點。但是,在「deque_lock.unlock();」之後沒有保證沒有併發線程不會在雙端隊列中添加對象。然後當前線程將等待,而該deque不是空的。因此,我認爲這裏仍然存在數據競賽。 –

+1

這取決於你想要在隊列中擁有什麼狀態。條件變量經常用於等待,而隊列不是空的,有兩個元素不會打擾你。作爲事後的想法,我想知道,爲什麼不用一個互斥體排除對隊列和鎖定條件變量的訪問,即只使用'locks.deque_mutex_ [st.id]'。這將完全排除你的數據競爭(如果這是一個合理的解決方案,我不能說這些代碼部分)。 –

相關問題