简体   繁体   English

使用条件变量同步三个线程

[英]Synchronizing three threads with Condition Variable

I have three threads in my application, the first thread needs to wait for a data to be ready from the two other threads. 我的应用程序中有三个线程,第一个线程需要等待其他两个线程准备好数据。 The two threads are preparing the data concurrently. 这两个线程正在同时准备数据。 In order to do that I am using condition variable in C++ as following: 为了做到这一点,我在C ++中使用条件变量如下:

boost::mutex mut;       
boost::condition_variable cond;     

Thread1: 线程1:

    bool check_data_received()
    {
         return (data1_received && data2_received);
    }

    // Wait until socket data has arrived
    boost::unique_lock<boost::mutex> lock(mut);
    if (!cond.timed_wait(lock, boost::posix_time::milliseconds(200),
        boost::bind(&check_data_received)))
    {

    }

Thread2: 线程2:

    {
        boost::lock_guard<boost::mutex> lock(mut);
        data1_received = true;
    }
    cond.notify_one();

Thread3: Thread3:

    {
        boost::lock_guard<boost::mutex> lock(mut);
        data2_received = true;
    }
    cond.notify_one();

So my question is it correct to do that, or is there any more efficient way? 所以我的问题是这样做是正确的,还是有更有效的方法? I am looking for the most optimized way to do the waiting. 我正在寻找最优化的等待方式。

It looks like you want a semaphore here, so you can wait for two "resources" to be "taken". 看起来你想要一个信号量,所以你可以等待两个“资源”被“采取”。

For now, just replace the mutual exclusion with an atomic. 现在,只需用原子替换互斥。 you can still use a cv to signal the waiter: 你仍然可以使用cv来通知服务员:

#include <boost/thread.hpp>

boost::mutex mut;       
boost::condition_variable cond;     

boost::atomic_bool data1_received(false);
boost::atomic_bool data2_received(false);

bool check_data_received()
{
    return (data1_received && data2_received);
}

void thread1()
{
    // Wait until socket data has arrived
    boost::unique_lock<boost::mutex> lock(mut);
    while (!cond.timed_wait(lock, boost::posix_time::milliseconds(200),
        boost::bind(&check_data_received)))
    {
        std::cout << "." << std::flush;
    }
}

void thread2()
{
    boost::this_thread::sleep_for(boost::chrono::milliseconds(rand() % 4000));
    data1_received = true;
    cond.notify_one();
}

void thread3()
{
    boost::this_thread::sleep_for(boost::chrono::milliseconds(rand() % 4000));
    data2_received = true;
    cond.notify_one();
}

int main()
{
    boost::thread_group g;
    g.create_thread(thread1);
    g.create_thread(thread2);
    g.create_thread(thread3);

    g.join_all();
}

Note: 注意:

  • warning - it's essential that you know only the waiter is waiting on the cv , otherwise you need notify_all() instead of notify_one() . 警告 - 您必须知道服务员正在等待cv ,否则您需要 notify_all()而不是notify_one()
  • It is not important that the waiter is already waiting before the workers signal their completion, because the predicated timed_wait checks the predicate before blocking. 在工作人员发出信号完成之前,服务员已经在等待并不重要,因为谓词timed_wait在阻塞之前检查谓词。
  • Because this sample uses atomics and predicated wait, it's not actually critical to signal the cv under the mutex. 因为此示例使用原子和谓词等待,所以在互斥锁下发出cv信号实际上并不重要。 However, thread checkers will (rightly) complain about this (I think) because it's impossible for them to check proper synchronization unless you add the locking. 但是,线程检查器会(正确地)抱怨这个(我认为),因为除非你添加锁定,否则它们不可能检查正确的同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM