C++ 等待多个互斥体的条件变量
我有一个C++ 等待多个互斥体的条件变量,c++,multithreading,c++11,mutex,condition-variable,C++,Multithreading,C++11,Mutex,Condition Variable,我有一个std::condition\u变量\u any,它等待由两个互斥体组成的自定义锁(一个std::mutex和一个共享锁定std::shared\u mutex)。它的unlock()操作只是按顺序解锁两个互斥锁 例如(伪代码): cv.wait() 当mutex1或mutex2中的任何一个被解锁后,它仍然保证线程正在休眠并侦听条件变量通知吗 或者有可能一个互斥锁被解锁,第二个线程将其锁定,并发送通知,但第一个线程尚未睡眠和侦听。因此,通知从未到达,也未发生唤醒。如果DualLock满足
std::condition\u变量\u any
,它等待由两个互斥体组成的自定义锁(一个std::mutex
和一个共享锁定std::shared\u mutex
)。它的unlock()
操作只是按顺序解锁两个互斥锁
例如(伪代码):
cv.wait()
当mutex1
或mutex2
中的任何一个被解锁后,它仍然保证线程正在休眠并侦听条件变量通知吗
或者有可能一个互斥锁被解锁,第二个线程将其锁定,并发送通知,但第一个线程尚未睡眠和侦听。因此,通知从未到达,也未发生唤醒。如果DualLock
满足BasicLockable
的要求,则代码将按预期执行。如果没有,就不会
基本时钟参考是
因此,通知从未到达,也未发生唤醒
如果正确使用条件变量,则永远不会发生这种情况。条件变量的唤醒不能解释为事件的信号,因为条件变量的文档说明可能存在虚假唤醒
充其量,该通知表示现在可能是测试您正在等待的条件的好时机(您可以在知道测试受互斥锁保护的安全情况下这样做)
当前线程的状态和阻塞状态是两个独立的关注点
下面是一个更好的示例(假设DualLock模型基本上可以正确计时):
您的通知程序将通过以下方式通知:
DualLock lock(unique_lock(mutex1), shared_lock(mutex2));
condition_met = true;
lock.unlock(); // note the order: unlock mutex first...
cv.notify_all(); // ...then notify the condition variable
因此,如果在等待线程上仍在执行cv.wait()->DualLock::unlock()
时调用cv.notify_all()
,则仍然可以保证wait
不会开始睡眠,而是立即返回?@tmlen自定义互斥锁的lock方法必须按照概念进行操作(即完全锁定互斥锁、阻塞互斥锁或引发异常)。如果你做对了,上面的代码将永远有效。这里的复杂之处在于双锁的实现,而不是cv。如果DualLock
不使用std::lock
锁定互斥锁,则有死锁的危险。您的伪代码在构造DualLock
的行中看起来有死锁的危险。
bool condition_met = false;
mutex mutex1;
shared_mutex mutex2;
condition_variable_any cv;
// acquiring the locks
DualLock lock(unique_lock(mutex1), shared_lock(mutex2));
while(!condition_met)
{
// waiting
cv.wait(lock);
}
// whatever happens, you have the lock here
// ...work
lock.unlock();
DualLock lock(unique_lock(mutex1), shared_lock(mutex2));
condition_met = true;
lock.unlock(); // note the order: unlock mutex first...
cv.notify_all(); // ...then notify the condition variable