【问题标题】:Boost Condition Variable with multiple threads使用多线程提升条件变量
【发布时间】:2014-03-15 13:21:24
【问题描述】:

在我的程序中,我有两个基本线程。第一个是主线程,第二个是 Tcp 服务器线程。 TCP 服务器将侦听请求,并为每个请求创建一个相应的线程,每个新创建的线程都应该开始工作,直到它们到达必须等待来自主线程的指示的某个点。为了解决这个问题,我正在使用 Boost 1.49 实现一个条件变量。

我的主要问题是每当任何新创建的线程到达条件变量的点时,我的整个程序都会冻结。

更多信息,请查看: Boost 1.49 Condition Variable issue

到目前为止,我没有收到任何积极的回应,也无法解决问题。

非常感谢。

【问题讨论】:

    标签: c++ multithreading boost


    【解决方案1】:

    我没有看你的其他问题(代码太多)

    不过,一般来说,您必须在相应的互斥锁下等待/发出条件信号。

    下面是一个由 10 名工人组成的小组等待开始信号的演示:

    • Live On Coliru

      #include <boost/thread.hpp>
      #include <boost/optional/optional_io.hpp>
      
      /////////////////////////
      // start condition logic
      
      boost::mutex mx;
      boost::condition_variable cv;
      
      static bool ok_to_start = false; 
      
      void await_start_condition()
      {
          boost::unique_lock<boost::mutex> lk(mx);
          cv.wait(lk, [] { return ok_to_start; });
      }
      
      void signal_start_condition()
      {
          boost::lock_guard<boost::mutex> lk(mx); 
          ok_to_start = true;
          cv.notify_all();
      }
      
      /////////////////////////
      // workers
      static boost::optional<int> shared_secret;
      
      void worker(int id)
      {
          await_start_condition();
      
          // demo worker implementation
          static boost::mutex console_mx;
          boost::lock_guard<boost::mutex> lk(console_mx);
          std::cout << "worker " << id << ": secret is " << shared_secret << "\n";
      }
      
      int main()
      {
          boost::thread_group threads;
      
          for (int i = 0; i<10; i++)
              threads.create_thread(boost::bind(worker, i));
      
          // demo - initialize some state before thread start
          shared_secret = 42;
      
          // signal threads can start
          signal_start_condition();
      
          // wait for all threads to finish
          threads.join_all();
      }
      
    • 对于 C++03,您可以用手写谓词替换 lambda:Live On Coliru

      namespace /* anon detail */
      {
          bool ok_to_start_predicate() { return ok_to_start; }
      }
      
      void await_start_condition()
      {
          boost::unique_lock<boost::mutex> lk(mx);
          cv.wait(lk, ok_to_start_predicate);
      }
      
    • 或者您可以使用 Boost Lambda/Boost Phoenix 为您解决问题:Live On Coliru

      #include <boost/phoenix.hpp>
      void await_start_condition()
      {
          boost::unique_lock<boost::mutex> lk(mx);
          cv.wait(lk, boost::phoenix::cref(ok_to_start));
      }
      

    【讨论】:

    • 感谢您的回复。但是我完全按照 boost 的文档来使用条件变量。在您的示例中,您让所有工作人员等待信号开始,但在我的情况下。每个请求都以与其他请求不同的方式处理。每个请求都有自己的互斥量和条件变量。
    • 也许您可以将其缩减为 SSCCE(也许以我的示例为起点?)
    • SSCCE和凤凰是什么意思?如果您想要关于我的问题的更短代码,您可以查看stackoverflow.com/questions/22401535/… 非常感谢。
    • 你知道,我回答了 this 问题。不是其他问题。我的意思是sscce.orgphoenix。顺便说一句,代码就在那里,在我的回答和 Coliru 上
    • 查看了另一个答案中的代码后,尝试将 notify_one 调用移到互斥锁下(请参阅我的答案中的 cmets)。可能存在竞争条件。此外,完全按照我在此示例中显示的那样使用谓词 wait() 重载(否则,即使条件已经设置,您也会等待。(没有足够的代码来查看是否真的会发生)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2011-10-02
    • 1970-01-01
    • 2023-03-04
    • 2022-01-03
    • 1970-01-01
    • 2013-01-12
    相关资源
    最近更新 更多