C++ 两个线程是否可以同时锁定一个互斥锁(使用互斥锁包装器)?

C++ 两个线程是否可以同时锁定一个互斥锁(使用互斥锁包装器)?,c++,C++,这个问题来自一系列的例子 据我所知,当我构造一个新的线程时,它立即开始执行 所以我想知道,cv.wait(lk,[]{returnready;})在worker\u-thread()和std::lock\u-guard lk(m)中在main中,是否同时锁定互斥锁?这会发生吗 (从cppreference中,我知道std::condition\u variable::wait和std::lock\u guard会在构造期间锁定互斥锁。) #包括 #包括 #包括 #包括 #包括 std::互斥m;

这个问题来自一系列的例子

据我所知,当我构造一个新的
线程时,它立即开始执行

所以我想知道,
cv.wait(lk,[]{returnready;})
worker\u-thread()
std::lock\u-guard lk(m)中
main
中,是否同时锁定互斥锁?这会发生吗


(从cppreference中,我知道
std::condition\u variable::wait
std::lock\u guard
会在构造期间锁定互斥锁。)

#包括
#包括
#包括
#包括
#包括
std::互斥m;
std::条件变量cv;
std::字符串数据;
bool ready=false;
bool-processed=false;
无效工作线程()
{
//等待main()发送数据
std::唯一锁lk(m);
cv.wait(lk,[{return ready;});
//等待之后,锁归我们所有。

std::cout互斥锁意味着获得资源上的锁,只有一个线程可以获得该锁。互斥锁的锁定是原子的,两个线程无法获得互斥锁的锁,如果可以的话,那么就违背了互斥锁的目的

互斥锁的构建使得锁定是一个原子操作:它一次只能在一个线程上完成,而不管有多少线程试图锁定

“互斥”是“互斥”的缩写;它的目的是在任何时候只允许一个线程锁定互斥

也就是说,在这个例子中有一个严重的问题,它有一个潜在的死锁,因为它试图对本质上不连续的操作进行排序

如果在新线程锁定互斥锁并调用
wait()
之前,
main
通过其锁定代码,将
ready
设置为
true
,并调用
notify()
,就会出现问题。如果发生这种情况,
main
将在新线程处于
wait>状态时继续调用
wait()
()
,两个人都不会通知另一个人;他们都在等待另一个人做某事


如果您运气不好,那么在测试代码时不会看到这一点;新线程可能会在主线程调用
notify()之前开始
wait()
,然后代码将按预期工作。这是不幸运的,因为它迟早会锁定,很可能是在您向最重要的客户演示代码时锁定的。

std::condition\u variable::wait 1)_u_自动释放锁,阻止当前正在执行的线程,并将其添加到等待*this的线程列表中。当notify_all()或notify_one()时,该线程将被解除阻止被执行。它也可能被错误地解除阻止。解除阻止后,无论原因如何,都会重新获取锁并等待退出。如果此函数通过异常退出,则也会重新获取锁。
哇,谢谢,你说得对,我没有注意到。也许你应该提醒cppreference关于此示例。
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>

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