通知线程是否有可能在被通知线程等待锁定之前锁定?

Is it possible for the notifying thread to lock before the notified thread's wait to lock?

来自 std::condition_variable::notify_one 的示例代码。

我的问题是:
通知线程是否有可能在通知线程的wait函数之前锁定锁定,因为 notify 操作不会阻塞当前线程?


代码:(我删除了原来的注释)

#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>

std::condition_variable cv;
std::mutex cv_m;
int i = 0;
bool done = false;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << "Waiting... \n";
    cv.wait(lk, []{return i == 1;}); //Waiting 
    std::cout << "...finished waiting. i == 1\n";
    done = true;
}

void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Notifying falsely...\n";
    cv.notify_one(); //Notifying

    std::unique_lock<std::mutex> lk(cv_m);//Is it possible for this line to execute
                                         //before cv.waits() in waits() tries to lock ?
    i = 1;
    while (!done)
    {
        std::cout << "Notifying true change...\n";
        lk.unlock();
        cv.notify_one(); 
        std::this_thread::sleep_for(std::chrono::seconds(1));
        lk.lock();
    }
}

int main()
{
    std::thread t1(waits), t2(signals);
    t1.join();
    t2.join();
}

回答你的标题问题,是的。 signals 线程可能先于 waits 线程锁定。但在回答你真正的问题时,不,这不会导致僵局。

为什么?

因为在示例中,互斥量由 lk.unlock() 释放。在此解锁时,waits 线程将有机会锁定(然后在等待开始时再次解锁)。

此循环一直持续到 wait 线程用 done 布尔值表示它已完成。

时间示例:

还有很多其他的,但在所有情况下,相关的 objects 和条件变量都受互斥量保护。你不能有数据竞争或死锁。这个例子很好。