阻塞主线程等待它的子线程

block the main thread to wait for its child threads

所以我有这个 class:

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 函数吗?

您需要在 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

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

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

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

空无限循环,因为 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
}