2014-02-16 105 views
0

我有以下計時代碼,它似乎沒有等待條件變量根據需要。目標是產生所有線程,然後讓他們同時開始工作。正確使用條件變量

過早似乎被稱爲。任何想法爲什麼?

chrono::milliseconds timeNThreadsLockFree(int n, int worksize) 
{ 
    boost::lockfree::stack<int> data(totalNumberOfWorkItems); 
    vector<thread> ts; 
    atomic<int> count; 
    condition_variable cv; 
    mutex mut2; 
    unique_lock<mutex> ul(mut2,defer_lock); 
    lock(ul,mut); 
    auto startSpawn = chrono::high_resolution_clock::now(); 
    for (int i = 0; i < n; i++) 
     ts.push_back(thread([&](){ 
     cv.wait(ul, [](){return true; }); 
     int q = 5; 
     for (int j = 0; j < worksize; j++){ 
      data.push(7); 
      else count++;} 
    })); 
    if (count != 0) { 
     cout << "premature" << endl; } 
    cv.notify_all(); 
    auto startWait = chrono::high_resolution_clock::now(); 
    for (auto&& t : ts) 
     t.join(); 
    auto endWait = chrono::high_resolution_clock::now(); 
    if (count != totalNumberOfWorkItems) 
     cout << "not done" << endl; 
    return chrono::duration_cast<chrono::milliseconds>(endWait - startWait); 
} 

回答

0

我認爲問題是與cv.wait調用的第二個參數。 cppreference說,第二個參數中,當虛假喚醒時,稱爲謂詞,那:

謂詞返回假,如果等待應該繼續

所以,以確保鎖定的實際工作,你應該做一個變量像在主函數ready,然後使用該等待中:

bool ready = false; 
... 
cv.wait(ul, [](){ return ready; }); 
... 
ready = true; 
cv.notify_all(); 

此外,你可能想嘗試做一個單獨的std::unique_lock爲每個線程,而不是重新利用的主要功能之一:

ts.push_back(thread([&]() { 
    std::unique_lock<std::mutex> ul2(mut2); 
    cv.wait(ul2, [](){ return ready; }); 

然後,你還需要解除舊鎖主要功能:

ready = true; 
ul.ulock(); 
cv.notify_all(); 

最後,因爲你希望所有的線程在同一時間運行,你可能會想手動解鎖內std::unique_lock這麼一個以上的可運行:

ts.push_back(thread([&]() { 
    std::unique_lock<std::mutex> ul2(mut2); 
    cv.wait(ul2, [](){ return ready; }); 
    ul2.unlock(); 
+0

如果我刪除拉姆達我得到「鎖定正在舉行由不同的上下文」的斷言在Visual Studio中失敗。如果我使lambda返回false,那也是一樣。想法? – soandos

+0

另一件需要注意的事情是,我從來不希望鎖需要重新獲取。在這種情況下是否做到了? – soandos

+0

@soandos如果你嘗試在每個線程內部用相同的互斥體創建一個單獨的'std :: unique_lock',然後嘗試等待呢? – Xymostech

0

有一堆鎖/解鎖/等待/通知各地通常是一個線索,你正在使用錯誤的工具。使用boost::barrier(或滾你自己,這是微不足道的實施):

boost::barrier bar(n+1); 
for (int i = 0; i < n; i++) 
    ts.push_back(thread([&](){ 
     bar.wait(); 
     // ... 
    })); 
// ... 
bar.wait(); // after this line all threads will be released from the barrier