【问题标题】:Not all threads notified of condition_variable.notify_all()并非所有线程都通知了 condition_variable.notify_all()
【发布时间】:2016-11-06 04:13:28
【问题描述】:

我有以下场景:

condition_variable cv;
mutex mut;

// Thread 1:
void run() {
    while (true) {
        mut.lock();
        // create_some_data();
        mut.unlock();
        cv.notify_all();        
    }
}

// Thread 2
void thread2() {
    mutex lockMutex;
    unique_lock<mutex> lock(lockMutex);
    while (running) {
        cv.wait(lock);
        mut.lock();
        // copy data
        mut.unlock();
        // process data
    }
}

// Thread 3, 4... - same as Thread 2

我一直运行线程 1 来获取新数据。其他线程使用 condition_variable 等待,直到有新数据可用,然后复制它并对其进行一些工作。线程执行的工作在完成所需的时间上有所不同,其想法是线程只有在完成旧数据时才会获取新数据。同时获得的数据允许“遗漏”。我不使用共享互斥锁(仅用于访问数据),因为我不希望线程相互依赖。

上面的代码在 Windows 上运行良好,但现在我在 Ubuntu 上运行它,我注意到当 notify_all() 被调用时只有一个线程被通知,而其他线程只是挂在 wait() 上。 这是为什么? Linux 是否需要不同的方法来使用 condition_variable?

【问题讨论】:

  • I don't use shared mutex (only to access data) because I don't want threads to depend on each other. - 但是使用条件变量 需要 共享互斥锁。没有别的办法。

标签: c++ multithreading condition-variable


【解决方案1】:

您的代码会立即显示 UB,因为它会重新锁定 cv 在退出等待时重新锁定的唯一锁。

还有其他问题,例如无法检测到虚假唤醒。

最后 cv 通知所有 onky 通知当前正在等待的线程。如果稍后出现线程,则没有骰子。

【讨论】:

    【解决方案2】:

    运气不错。

    互斥体和条件变量是同一个结构的两个部分。您不能混合和匹配互斥锁和 cvs。

    试试这个:

    void thread2() {
        unique_lock<mutex> lock(mut); // use the global mutex
        while (running) {
            cv.wait(lock);
            // mutex is already locked here
            // test condition. wakeups can be spurious
            // copy data
            lock.unlock();
            // process data
    
            lock.lock();
        }
    }
    

    【讨论】:

    • 感谢大家对看似简单而愚蠢的错误的回答。我接受了这个作为答案,因为它也满足了我的要求,即在循环的其余部分不锁定互斥锁。
    【解决方案3】:

    this documentation:

    任何打算在 std::condition_variable 上等待的线程都必须

    1. 获取一个 std::unique_lock,在同一个互斥锁上 保护共享变量
    2. 执行 wait、wait_for 或 wait_until。等待操作原子地释放互斥锁并暂停执行 线程。
    3. 当通知条件变量,超时超时,或者发生虚假唤醒时,线程被唤醒,互斥量被 原子地重新获得。然后线程应该检查条件 如果唤醒是虚假的,则继续等待。

    这段代码

    void thread2() {
        mutex lockMutex;
        unique_lock<mutex> lock(lockMutex);
        while (running) {
    

    不这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 2017-05-28
      相关资源
      最近更新 更多