为什么lock_guard可以通过unique_lock获取已经锁定的互斥锁? - 仍然有问题

时间:2015-08-31 14:00:27

标签: c++ multithreading c++11

我正在研究this example。我找到this question并认为我会得到答案,但我还有一个问题。

为方便起见,我在这里发布了代码:

std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;

void worker_thread()
{
    // Wait until main() sends data
    std::cout << "------------------------\n";
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});

    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";

    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";

    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}

int main()
{
    std::thread worker(worker_thread);

    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();

    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';

    worker.join();

    return 0;
}

语句std::unique_lock<std::mutex> lk(m);是否应该阻止主线程,因为m锁定了互斥worker_thread?如果是,在此示例中不需要语句cv.wait(lk, []{return processed;});之后?当主线程可以锁定互斥锁时,processed将已经为真。

2 个答案:

答案 0 :(得分:1)

wait的调用会在等待期间解锁互斥锁。请参阅http://en.cppreference.com/w/cpp/thread/condition_variable/wait

编辑:您在链接到的问题的答案中明确说明了这一点:https://stackoverflow.com/a/32030975/212870

编辑2:“当主线程可以锁定互斥锁时,processed已经为真”,这是不正确的。工作线程可能尚未启动,或者如果有,可能没有看到ready已设置。

答案 1 :(得分:0)

如果cv.wait(lk, []{return ready;});ready

,则

false执行以下操作

  1. 解锁互斥锁lk

  2. 阻止线程等待通知

  3. 当通知到达时,取消阻止线程并锁定互斥锁lk

  4. 因为工作线程解锁了互斥锁,所以主线程不会阻塞std::lock_guard<std::mutex> lk(m);