正确使用条件变量

时间:2014-02-16 01:04:24

标签: c++11 condition-variable

我有以下时序代码,似乎没有按需要等待条件变量。目标是生成所有线程,然后让它们全部同时开始工作。

过早似乎被称为。有什么想法吗?

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);
}

2 个答案:

答案 0 :(得分:0)

我认为问题在于cv.wait调用的第二个参数。 cppreference表示在发生虚假唤醒时调用的谓词的第二个参数,并且:

  

谓词如果等待应该继续,则返回false

因此,为了确保锁定确实有效,你应该在main函数中创建一个像ready这样的变量,然后在等待中使用它:

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

另外,您可能想尝试为每个线程单独std::unique_lock,而不是重新使用main函数中的那个:

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

然后,您还需要解锁main函数中的旧锁:

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();

答案 1 :(得分: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