c++ - condition_variable_any 与 recursive_mutex 一起使用时的行为?

标签 c++ multithreading c++11 boost recursive-mutex

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在等待通知时被其他线程获取。

Class condition_variable_any

template<typename lock_type> void wait(lock_type& lock)

Effects:

Atomically call lock.unlock() and blocks the current thread. The thread will unblock when notified by a call to this->notify_one() or this->notify_all(), or spuriously. When the thread is unblocked (for whatever reason), the lock is reacquired by invoking lock.lock() before the call to wait returns. The lock is also reacquired by invoking lock.lock() if the function exits with an exception.

所以 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++ - condition_variable_any 与 recursive_mutex 一起使用时的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11752155/

相关文章:

c++ - 我如何在 C++11 中实现类似 "interrupted exception"行为的 Java

c++ - 从 vector C++ 返回结构元素

c++ - 如何将结构数组传递给C++

c++ - 从迭代器中的函数指针调用函数

multithreading - 如何使用 Spring Framework 调用 Runnable?

python-3.x - 如何在 Python 3 中导入线程包?

c++ - 对于可移动类型,按值传递比重载函数更好吗?

android - 如何从 Android 应用程序调用 C/C++ 二进制文件(在 linux 服务器上移植)

c++ - 调整结构中的 vector 的大小

c# - 正确实现多线程+套接字应用