是否有2个线程可以同时锁定互斥锁(使用互斥包包装)?

时间:2018-11-11 07:01:53

标签: c++

问题来自std::condition_variable

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

所以我想知道,cv.wait(lk, []{return ready;});中的worker_thread()std::lock_guard<std::mutex> lk(m);中的main是否会同时锁定互斥锁?这会发生吗?

(从cppreference中,我知道std::condition_variable::waitstd::lock_guard将在构造期间锁定互斥锁。)

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

2 个答案:

答案 0 :(得分:3)

Mutex旨在获取资源锁,只有1个线程可以获取该锁。互斥锁的锁定是原子的,两个线程无法获得互斥锁的锁,如果可以的话,那么就无法实现互斥锁的目的!

  

Mutexes的构建使锁定是一项原子操作:无论一次尝试锁定多少线程,它一次只能在一个线程上完成

答案 1 :(得分:1)

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

也就是说,该示例中存在一个严重的问题。它有潜在的死锁,因为它会尝试对固有的非顺序操作进行排序。

如果main经历了其锁定代码,将ready设置为true,并在新线程锁定互斥锁并调用{{1 }}。如果发生这种情况,当新线程位于notify()中时,wait()将继续其对main的调用,并且没有人通知另一个。他们俩都在等待对方做某事。

如果您不走运,则在测试代码时不会看到此内容。新线程可能会在主线程调用wait()之前开始运行到wait(),然后代码将按预期工作。这很不幸,因为它迟早会锁定,很可能是在向最重要的客户演示代码时出现的。