C++ 如何确保所有从线程都等待条件变量?

C++ 如何确保所有从线程都等待条件变量?,c++,multithreading,c++11,boost-thread,C++,Multithreading,C++11,Boost Thread,我正在运行以下代码块。这段代码将创建5个从线程和1个主线程。所有从属线程等待主线程准备好数据,当数据准备好时,所有从属线程将通知开始处理 我的问题是,在从属线程开始等待条件_变量之前,主线程可能会准备好数据并通知等待的线程。在这种情况下,一些等待的线程将获得通知并开始处理,而那些没有等待的线程将开始等待一个永远不会出现的通知 如果您运行这个示例,这种情况不会发生,但是我正在寻找一种方法来确保所有从线程都在等待通知,然后通知它们。你知道我怎么做吗 /* Condition Variables

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

我的问题是,在从属线程开始等待
条件_变量之前,主线程可能会准备好数据并通知等待的线程。在这种情况下,一些等待的线程将获得通知并开始处理,而那些没有等待的线程将开始等待一个永远不会出现的通知

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

/*
  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;
}
/*
条件变量-许多等待线程
显示如何使用一个条件变量通知多个线程
发生了一种情况。
*“带增压的螺纹-第四部分:条件变量”的一部分,发布于:
http://antonym.org/boost
版权所有(c)2015加文·贝克
根据MIT许可证发布,请参阅许可证以了解详细信息
*/
#包括
#包括
boost::条件变量数据就绪条件;
boost::互斥数据\u就绪\u互斥;
bool data_ready=false;
无效主螺纹()
{
printf(“+++主线程\n”);
//假装工作
printf(“主睡眠…\n”);
boost::chrono::毫秒睡眠持续时间(750);
boost::this_线程::sleep_for(sleepDuration);
//让其他线程知道我们完成了
printf(“主通知…\n”);
数据_ready=true;
数据准备就绪。通知所有人();
printf(“---主线程\n”);
}
无效从线程(内部id)
{
printf(“+++从线程:%d\n”,id);
boost::唯一的锁(数据就绪的互斥锁);
当(!数据准备就绪)
{
数据准备就绪条件等待(锁定);
}
printf(“---从线程:%d\n”,id);
}
int main()
{
printf(“生成线程…\n”);
boost::线程从线程1(从线程1);
boost::线程从线程2(从线程2);
boost::线程从线程3(从线程3);
boost::线程从线程4(从线程4);
主线程(主线程);
printf(“等待线程完成…\n”);
slave_1.join();
slave_2.join();
slave_3.join();
从属_4.连接();
master.join();
printf(“完成”\n);
返回0;
}

您有竞争条件-设置标志和通知从属线程不是原子的。因此,在修改主线程中的
data\u ready
标志之前,只需锁定
data\u ready\u互斥锁即可。这将消除争用条件,从线程将看到
data\u ready
false并转到等待条件变量,并将收到通知,或者,只有在
data\u ready
设置为
true
后,它才会获取互斥锁,因此它根本不会等待。

您有竞争条件-设置标志,通知从属线程不是原子的。因此,在修改主线程中的
data\u ready
标志之前,只需锁定
data\u ready\u互斥锁即可。这将消除争用条件,从属线程要么会看到
data\u ready
false并转到wait on condition变量并收到通知,要么只有在
data\u ready
设置为
true
后,它才会获取互斥锁,因此它根本不会等待。

您的条件谓词是
data\u ready
,您在
master_-thread
中修改它,而不使用互斥锁,互斥锁的唯一目的是保护它。这本身是错误的。@mmostajab您启动了从线程。只要谓词数据得到了适当的保护(它目前不在master中),它们是否依次锁存、检查和输入了wait(从而取消锁存)就不是特别相关的。如果你真的想确保所有的奴隶都在等待,那么多做一点工作是可能的,但坦率地说,这也是毫无意义的。“我喜欢确保所有的奴隶都在等待”-为什么?如果谓词数据得到了正确的管理,那么无论它们是否处于cvar等待状态(这在某种程度上是正确谓词管理的要点)。@mmostajab它根本不会发生,wait()将暂停执行并自动解锁互斥锁。我认为你没有抓住这一点。因此,如果在等待()之前从线程将被挂起,互斥锁将保持锁定。@mmostajab计数器不会消除这个问题,它是一个如何计算有多少从线程正在等待的答案,不管您出于什么原因需要它。如果您仍然认为需要确保所有从机都在等待消除讨论的问题,那么您就错了。您的条件谓词是
数据准备就绪
,并且您正在
主线程
中修改它,而没有互斥锁,互斥锁的唯一目的是保护它。这本身是错误的。@mmostajab您启动了从线程。只要谓词数据得到了适当的保护(它目前不在master中),它们是否依次锁存、检查和输入了wait(从而取消锁存)就不是特别相关的。如果你真的想确保所有的奴隶都在等待,那么多做一点工作是可能的,但坦率地说,这也是毫无意义的。“我喜欢确保所有的奴隶都在等待”-为什么?如果谓词数据得到了正确的管理,那么无论它们是否处于cvar等待状态(这在某种程度上是正确谓词管理的要点)。@mmostajab它根本不会发生,wait()将暂停执行并自动解锁互斥锁。我认为你没有抓住这一点。因此,如果在等待()之前从线程将被挂起,互斥锁将保持锁定。@mmostajab计数器不会消除这个问题,它是一个如何计算有多少从线程正在等待的答案,不管您出于什么原因需要它。如果您仍然认为需要确保所有从属服务器都在等待解决问题