在多线程环境中,我们具有以下两个功能:

std::mutex mtx;
std::condition_variable cv;

void waiter()
{
   std::unique_lock<std::mutex> lck(mtx);
   //...
   cv.wait(lck);
   //...
}

void notifier()
{
   std::unique_lock<std::mutex> lck(mtx);
   //...
   cv.notify_one();
}


假设服务员首先执行,然后等待condition_variable。然后,通知程序将执行并通知服务员。通知程序释放互斥量后,服务员将尝试重新获取它。

问题:是否有其他线程在通知程序释放互斥锁之后但仍在服务员获取互斥锁之前锁定了互斥锁?如果是,那么该怎么做才能避免这种情况发生?如果是的话,我也不了解condition_variable的目的。目的应该是阻塞线程,直到满足某些条件为止。但是,如果在条件满足并且线程被唤醒之后,又有机会再次不满足条件,那有什么意义呢?

最佳答案

是否有其他线程在通知程序释放互斥体之后但仍在服务员获取互斥体之前锁定了互斥体?


是。


  如果是,那么该怎么做才能避免这种情况发生?


没有。


  如果是的话,我也不理解condition_variable的目的。目的应该是阻塞线程,直到满足某些条件为止。但是,如果在条件满足并且线程被唤醒之后,又有机会再次不满足条件,那有什么意义呢?


更复杂了。如果根本没有通知条件变量,则可以唤醒线程。这称为伪唤醒(doc)。

条件变量的要点是阻塞线程,直到其他线程通知它为止。为了解决“当等待线程有机会执行时条件不满足”的问题,通常等待线程在循环中等待,直到条件满足。标准库甚至有一个快捷方式,有void wait( std::unique_lock<std::mutex>& lock, Predicate pred );重载可以做到这一点。请参见doc

关于c++ - C++:互斥体从通知程序到服务员的传递是否无缝?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40440712/

10-16 13:04