【问题标题】:Understanding std::condition_variables了解 std::condition_variable
【发布时间】:2015-12-22 23:13:36
【问题描述】:

当我有多个线程等待执行时,我试图了解 condition_variable 的流程。据我了解,所有线程都会尝试获取唯一锁,一个会获取它然后进入wait(),如果您调用notify_all,最多不会有一个线程等待允许通过。直到它释放它的锁并允许其他线程通过。

cv 是否与唯一锁通信并让所有线程同时通过?如果是这样,是真的一次完成,还是线程一个接一个地依次通过。

std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{return i == 1;});
    std::cerr << "...finished waiting. i == 1\n";
}

http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all

【问题讨论】:

    标签: c++ c++11 condition-variable


    【解决方案1】:

    虽然线程确实必须一次调用一个wait,但在它们等待时,它们不会持有锁。所以额外的线程可以通过wait函数。

    【讨论】:

      【解决方案2】:

      当您调用wait(单参数版本)时,锁被解锁并且线程进入等待状态,直到CV 被“通知”。当线程唤醒时,锁会再次被锁定。

      当你调用notify_one时,基本上会通知一个在CV上等待的随机线程。当您调用 notify_all 时,所有等待 CV 的线程都将从等待状态中唤醒,第一个锁定锁的线程将继续执行。 哪个也是随机的。

      请注意,当我说“随机”时,系统上线程的实际实现(从 C++ 库到操作系统内核,甚至可能是硬件)可能会以某种方式实现,从而可以推断出哪个线程将是唤醒并获得锁的线程,但从我们使用条件变量的应用程序编写者的角度来看,没有预定的顺序,它是随机的。

      【讨论】:

      • 所以第一个获得锁的人通过等待,直到它释放它的锁。所以他们被允许按顺序而不是一次全部通过。谢谢
      • @JoshuaWaring 值得一提的是,解锁和进入等待状态(wait 内部)需要原子发生。
      • 为了完整起见,大多数 POSIX 实现都允许虚假唤醒,这意味着在极少数情况下(更常见于激烈争用),notify_one 可以唤醒多个线程。更准确地说,POSIX 示例实现允许底层函数pthread_cond_signal 唤醒一个等待线程和任意数量的即将开始等待的线程。因此,即使使用单个 notify_one 来执行特定任务,仍然需要例如锁定一个互斥体。
      猜你喜欢
      • 1970-01-01
      • 2022-10-08
      • 2012-11-02
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多