通过对 Boost 文档的严格解释,我得出的结论是,在等待通知时通常不会condition_variable_any::wait
导致其他线程可以获取。recursive_mutex
班级condition_variable_any
template<typename lock_type> void wait(lock_type& lock)
效果:
原子地调用lock.unlock()
和阻塞当前线程。当调用this->notify_one()
or
this->notify_all()
或虚假通知时,线程将解除阻塞。当线程被解除阻塞时(无论出于何种原因),在lock.lock()
等待调用返回之前调用会重新获取锁。lock.lock()
如果函数因异常退出,也会通过调用来重新获取锁。
所以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(¬ifier);
t1.join();
t2.join();
}
我希望这可以帮助其他在混合condition_variable_any
和recursive_mutex
.