C++ 与递归\u互斥体一起使用时,条件\u变量\u any的行为?

C++ 与递归\u互斥体一起使用时,条件\u变量\u any的行为?,c++,multithreading,c++11,boost,recursive-mutex,C++,Multithreading,C++11,Boost,Recursive Mutex,当将条件变量\u any与递归互斥体一起使用时,当条件变量\u 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(

当将
条件变量\u any
递归互斥体一起使用时,当
条件变量\u 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?
}
void bar();
递归互斥互斥体;
boost::条件变量任何条件变量;
void foo()
{
boost::lock_guard lock(互斥锁);
//所有权级别现在是1
bar();
}
空条()
{
boost::唯一的锁(互斥锁);
//所有权级别现在是2
等待(锁);
//这是否完全释放了递归互斥体,
//这样其他线程可以在我们等待时获取它?
//递归\u互斥对象的所有权级别
//等待后恢复到两个?
}

通过对Boost文档的严格解释,我得出结论,
条件变量\u any::wait
通常不会导致其他线程在等待通知时获取
递归互斥锁

条件变量\u任意

模板无效等待(锁定类型和锁定)

影响:

自动调用
lock.unlock()
并阻止当前线程。当调用
this->notify_one()
this->notify_all()
,或伪造。当线程被解锁时(对于 无论什么原因),通过调用
lock.lock()
在等待调用返回之前。该锁也可由重新获取 如果函数带异常退出,则调用
lock.lock()

因此
condvar.wait(lock)
将调用
lock.unlock
,这反过来调用
mutex.unlock
,这会将所有权级别降低1(不一定降到零)


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

#包括
#定义使用1
#如果使用(u BOOST),
#包括
#包括
#包括
#包括
#包括
名称空间lib=boost;
#否则
#包括
#包括
#包括
#包括
名称空间lib=std;
#恩迪夫
空心钢筋();
lib::递归_互斥体互斥体;
lib::条件变量任意条件变量;
int值=0;
void foo()
{

std::cout您可以通过向在
互斥对象上运行的每个函数添加一个参数
allowed\u unlock\u count
来修复此设计;对于
allowed\u unlock\u count
,可以做出两种类型的保证:

(允许解锁深度)
允许解锁计数
表示
互斥锁的允许解锁深度
:调用者允许
解锁互斥锁
允许解锁计数
次。解锁后,不保证
互斥锁的状态

(承诺解锁)
允许的解锁计数
表示
互斥锁的锁定深度
:调用者保证解锁
互斥锁
的准确时间
允许的解锁计数
将允许其他线程抓取
互斥锁
对象

这些保证是函数的前置和后置条件

这里的
条码取决于(承诺解锁)

// pre: mutex locking depth is allowed_unlock_count
void bar(int allowed_unlock_count)
{
    // mutex locking depth is allowed_unlock_count
    boost::unique_lock<boost::recursive_mutex> lock(mutex);
    // mutex locking depth is allowed_unlock_count+1

    // you might want to turn theses loops
    // into an a special lock object!
    for (int i=0; i<allowed_unlock_count; ++i)
        mutex.unlock();
    // mutex locking depth is 1

    condvar.wait(lock); // other threads can grab mutex

    // mutex locking depth is 1
    for (int i=0; i<allowed_unlock_count; ++i)
        mutex.lock();
    // mutex locking depth is allowed_unlock_count+1
}
// post: mutex locking depth is allowed_unlock_count
//前置:允许互斥锁深度\u解锁\u计数
无效条(允许整数\u解锁\u计数)
{
//允许互斥锁深度\u解锁\u计数
boost::唯一的锁(互斥锁);
//允许互斥锁深度\u解锁\u计数+1
//你可能想把这些循环
//变成一个特殊的锁定对象!

对于(int i=0;iI在Boost文档中找不到任何关于混合
条件变量\u any
递归\u互斥体的信息。您期望(或希望)了吗调用
wait
使互斥锁解锁?@curiousguy:是的,我有点这样做。这种行为会使它不太可能遇到死锁问题。调用函数呢?它是否期望
bar()
解锁互斥锁?这里的问题是
bar()的契约
允许它与其他地方的锁混淆。如果你想让这是你的设计,你需要让它非常明确。@curiousguy,我没有在我的任何东西中使用
递归互斥锁
。我只是在这里读另一个问题时遇到它,想知道它如何与条件变量互操作。请解释一下下一票?我的推理有缺陷吗?不是我的下一票,但我支持它,因为答案并没有回答真正的问题,只是声称它是无法解决的。问题应该是“我如何使用递归互斥的条件变量”让人大吃一惊。+1表示假定的有意欢笑。+1 C++11规范与boost非常相似文档。这是一个罕见的情况下的推进遵循C++草案(当时)相反。
condition\u variable\u any
是在中提出的,当时的规范要求递归锁的锁计数在进入等待时为1。具体的措辞已经改变,但意图没有改变。boost随后选择了它。
// pre: mutex locking depth is allowed_unlock_count
void bar(int allowed_unlock_count)
{
    // mutex locking depth is allowed_unlock_count
    boost::unique_lock<boost::recursive_mutex> lock(mutex);
    // mutex locking depth is allowed_unlock_count+1

    // you might want to turn theses loops
    // into an a special lock object!
    for (int i=0; i<allowed_unlock_count; ++i)
        mutex.unlock();
    // mutex locking depth is 1

    condvar.wait(lock); // other threads can grab mutex

    // mutex locking depth is 1
    for (int i=0; i<allowed_unlock_count; ++i)
        mutex.lock();
    // mutex locking depth is allowed_unlock_count+1
}
// post: mutex locking depth is allowed_unlock_count