condition_variable_anyrecursive_mutex 一起使用时,recursive_mutex 是否可以在 condition_variable_any::wait 等待时从其他线程获得?我对 Boost 和 C++11 实现都感兴趣。

这是我主要关心的用例:

void bar();

boost::recursive_mutex mutex;
boost::condition_variable_any condvar;

void foo()
{
    boost::lock_guard<boost::recursive_mutex> lock(mutex);
    // Ownership level is now one

    bar();
}

void bar()
{
    boost::unique_lock<boost::recursive_mutex> lock(mutex);
    // Ownership level is now two

    condvar.wait(lock);
   // Does this fully release the recursive mutex,
   // so that other threads may acquire it while we're waiting?
   // Will the recursive_mutex ownership level
   // be restored to two after waiting?
}

最佳答案

通过对 Boost 文档的严格解释,我得出的结论是 condition_variable_any::wait 通常不会导致 recursive_mutex 在等待通知时被其他线程获取。



所以 condvar.wait(lock) 将调用 lock.unlock ,后者又调用 mutex.unlock ,这将所有权级别降低一(不一定降到零)。

我编写了一个测试程序来证实我的上述结论(对于 Boost 和 C++11):

#include <iostream>

#define USE_BOOST 1

#if USE_BOOST

#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/recursive_mutex.hpp>
namespace lib = boost;

#else

#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
namespace lib = std;

#endif

void bar();


lib::recursive_mutex mutex;
lib::condition_variable_any condvar;
int value = 0;

void foo()
{
    std::cout << "foo()\n";
    lib::lock_guard<lib::recursive_mutex> lock(mutex);
    // Ownership level is now one

    bar();
}

void bar()
{
    std::cout << "bar()\n";
    lib::unique_lock<lib::recursive_mutex> lock(mutex);
    // Ownership level is now two

    condvar.wait(lock); // Does this fully release the recursive mutex?

    std::cout << "value = " << value << "\n";
}

void notifier()
{
    std::cout << "notifier()\n";
    lib::this_thread::sleep_for(lib::chrono::seconds(3));
    std::cout << "after sleep\n";

    // --- Program deadlocks here ---
    lib::lock_guard<lib::recursive_mutex> lock(mutex);

    value = 42;
    std::cout << "before notify_one\n";
    condvar.notify_one();
}

int main()
{
    lib::thread t1(&foo); // This results in deadlock
    // lib::thread t1(&bar); // This doesn't result in deadlock
    lib::thread t2(&notifier);
    t1.join();
    t2.join();
}

我希望这可以帮助其他人在混合 condition_variable_anyrecursive_mutex 时面临同样的困境。

关于c++ - 与 recursive_mutex 一起使用时 condition_variable_any 的行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11752155/

10-11 18:00