【问题标题】:How to make sure all slave threads are waited for conditional variable?如何确保所有从线程都等待条件变量?
【发布时间】:2015-09-18 19:30:23
【问题描述】:

我正在运行以下代码块。此代码将创建 5 个从线程和 1 个主线程。所有从线程都在等待主线程准备好数据,当数据准备好时,所有从线程都会通知开始处理。

我的问题是,有可能在从线程开始等待conditional_variable 之前,主线程准备好数据并通知等待的线程。在这种情况下,一些被等待的线程会收到通知并开始处理,而那些没有等待的线程将开始等待一个永远不会到来的通知。

如果您运行此示例,则不会发生这种情况,但我正在寻找一种方法来确保所有从属线程都在等待通知,然后通知它们。你知道我该怎么做吗?

/*
  Condition Variables - Many waiting threads

  Shows how one condition variable can be used to notify multiple threads
  that a condition has occured.

  * Part of "Threading with Boost - Part IV: Condition Variables", published at:

      http://antonym.org/boost

  Copyright (c) 2015 Gavin Baker <gavinb@antonym.org>
  Published under the MIT license, see LICENSE for details
*/

#include <cstdio>

#include <boost/thread.hpp>

boost::condition_variable data_ready_cond;
boost::mutex data_ready_mutex;
bool data_ready = false;

void master_thread()
{
    printf("+++ master thread\n");

    // Pretend to work
    printf("    master sleeping...\n");
    boost::chrono::milliseconds sleepDuration(750);
    boost::this_thread::sleep_for(sleepDuration);

    // Let other threads know we're done
    printf("    master notifying...\n");
    data_ready = true;
    data_ready_cond.notify_all();

    printf("--- master thread\n");
}

void slave_thread(int id)
{
    printf("+++ slave thread: %d\n", id);

    boost::unique_lock<boost::mutex> lock(data_ready_mutex);
    while (!data_ready)
    {
        data_ready_cond.wait(lock);
    }

    printf("--- slave thread: %d\n", id);
}

int main()
{
    printf("Spawning threads...\n");

    boost::thread slave_1(slave_thread, 1);
    boost::thread slave_2(slave_thread, 2);
    boost::thread slave_3(slave_thread, 3);
    boost::thread slave_4(slave_thread, 4);

    boost::thread master(master_thread);

    printf("Waiting for threads to complete...\n");

    slave_1.join();
    slave_2.join();
    slave_3.join();
    slave_4.join();
    master.join();

    printf("Done\n");

    return 0;
}

【问题讨论】:

  • 您的条件谓词是data_ready,并且您在master_thread 中修改它而没有互斥体,其唯一目的是保护它,锁定。这本身就是错误的。
  • @mmostajab 您启动了从属线程。只要谓词数据受到适当保护(目前在主数据中),它们是否依次锁定、检查和进入等待(因此解锁)并不是特别相关.如果你真的想确保所有的奴隶都在等待,可以多做一些工作,但坦率地说,这也是相当没有意义的。
  • “我想确保所有的奴隶都在等待” - 为什么?如果谓词数据得到妥善管理,它们是否处于 cvar 等待状态都无关紧要(这在某种程度上是正确谓词管理的重点)。
  • @mmostajab 它根本不会发生,wait() 暂停执行并原子地解锁互斥锁。我认为你错过了这一点。因此,如果 slave 将在 wait() 之前挂起,则互斥锁将保持锁定状态。
  • @mmostajab 计数器不会消除问题,它是如何计算有多少从属线程正在等待的答案,无论出于何种原因您需要它。如果您仍然认为需要确保所有从属设备都在等待解决所讨论的问题,那您就错了。

标签: c++ multithreading c++11 boost-thread


【解决方案1】:

你有竞争条件 - 设置标志和通知从线程不是原子的。所以你只需要在主线程中修改data_ready 标志之前锁定data_ready_mutex。这将消除竞争条件,从线程要么会看到 data_ready false 并去等待条件变量并会收到通知,要么只有在 data_ready 设置为 true 后才会获取互斥锁,因此它不会等待完全没有。

【讨论】:

  • 这是我可以/会写的一样准确。 cvars+mutex 的基本规则很简单:永远不要更改、甚至检查谓词数据状态,除非谓词互斥锁被锁定。 主线程违反了该基本规则.上调了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 2015-04-15
相关资源
最近更新 更多