【问题标题】:block the main thread to wait for its child threads阻塞主线程等待其子线程
【发布时间】:2015-12-25 21:29:17
【问题描述】:

所以我有这门课:

class foo {
public:
        foo() { };
        void me1() const {
            while(1) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 0;
            }
        }
        void me2() const {
            while(1) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 1;
            }
        }
private:
    std::mutex m;
};

现在我想在两个不同的线程中运行这两个方法,我这样做:

int main() {

    foo myfoo;

    std::thread firstThread(&foo::me1, &myfoo);
    std::thread secondThread(&foo::me2, &myfoo);

    firstThread.detach();
    secondThread.detach();

    //while(1) { }

    return 0;
}

我不想等待这两个方法中的任何一个完成,它们会同时运行直到主线程被杀死。

在主线程结束时可以有某种无限循环吗? (喜欢评论的while(1) {})。

或者我应该调用某种sleep 函数?

【问题讨论】:

  • 如果它们会同时运行直到主线程被杀死,你为什么不干脆等待它们呢?您将等待它们直到它们死亡,如果主线程被杀死,那么两者都会死亡。如果他们两个都执行完了,主线程就没有目的了,他就可以死了。
  • @MariusMarusanici 在你的问题中你说你不需要等待它们,当你加入两个线程时,你只需等待它们都完成。因此,如果一个永远不会结束,那么您的主线程将永远不会结束,直到它被杀死,我以为是您在问。
  • @g24l 如果主线程结束,子线程也会被杀死,所以他需要
  • 从技术上讲,您的循环可能会导致未定义的行为:stackoverflow.com/q/3592557/212870
  • Omg ,只需从您的函数中删除那些 const 说明符或使互斥体可变,请。

标签: c++ multithreading stdthread


【解决方案1】:

您需要在 foo::me1()foo::me2() 中定义一个 exit condition 。如果你不知道该怎么做,那

sleep(/*number of seconds you want your program to run*/ );

会很好。

如果你定义一个终止子句,那么蛮力将是 暴露类似原子的东西:

class foo {
public:

std::atomic<int> me1done = false;
std::atomic<int> me2done = false;

        foo() { };
        void me1() {
            while(/* need exit condition here*/) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 0;
            }
            me1done = true;
        }
        void me2() {
            while(/*need exit condition here*/) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 1;
            }
            me2done = true;
        }


private:
    std::mutex m;

};

然后您可以通过每 x 秒轮询一次来签入 main。

int main(void)
{
// start your threads and detach

foo myfoo;

std::thread firstThread(&foo::me1, &myfoo);
std::thread secondThread(&foo::me2, &myfoo);

firstThread.detach();
secondThread.detach();

while( not (myfoo.me1done and myfoo.me2done ) )
{
sleep( /* some time */);
}

return 0;
}

如果你想更详细,你将不得不使用condition variables

【讨论】:

    【解决方案2】:

    如果你想确定这两个线程是否已经完成,你最好的选择实际上不是detach() 线程,而是在退出主线程之前join() 它们。也就是说,您将启动两个线程,它们将同时运行,一旦启动您只需join() 每个。当然,这是假设线程将终止。

    拥有detach()ed 线程实际上意味着您永远无法确定它是否已完成。这通常很少有用,我认为将detach() 添加到std::thread 是一个错误。但是,即使使用detach()ed 线程,您可以识别何时实现了目标而无需忙于等待。为此,您需要设置合适的变量来指示完成或进度,并让它们受到std::mutex 的保护。然后,主线程将在std::condition_variablewait(),在完成/进度更新时,各个线程将获得notify_once()ed,这将在合理的时间间隔内完成。一旦所有线程都表明它们已完成或已达到适当的目标,main() 线程就可以完成。

    单独使用计时器通常不是一个好方法。线程之间的信号传递通常是可取的,并且往往会创建一个响应速度更快的系统。您仍然可以使用wait() 的定时版本(即wait_until()wait_for()),例如,在怀疑某个线程以某种方式挂起或超时时发出警报。

    【讨论】:

      【解决方案3】:

      while(1) { } 的空无限循环是 UB。

      在里面添加一个睡眠是可以的。

      要无限运行foo::me1/foo::me2,您还有其他几种选择:

      int main()
      {
          foo myfoo;
      
          std::thread firstThread(&foo::me1, &myfoo);
          std::thread secondThread(&foo::me2, &myfoo);
      
          firstThread.join();  // wait infinitely as it never ends.
          secondThread.join(); // and so never reach 
      }
      

      或者干脆用主线程做一项工作:

      int main()
      {
          foo myfoo;
      
          std::thread firstThread(&foo::me1, &myfoo);
          myfoo.me2(); // work infinitely as it never ends.
      
          firstThread.join(); // and so never reach
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        • 1970-01-01
        • 2012-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多