30 June 2023

C++ 核心指南目录

“Don’t detach() a thread”

理由

要让线程任务存活在其创建的作用域范围外的情况很常见,但是通过分离的方式实现,会很难监控线程、很难与分离的线程通信。尤其是,很难确保线程是否按照预期的方式结束,线程可能会存活超出预期的时间。

例子

void heartbeat();

void use()
{
    std::thread t(heartbeat);             // don't join; heartbeat is
                                          // meant to run forever
    t.detach();
    // ...
}

这个例子展示了使用线程的很合理的方式。这种情况 detach() 用得很多。但是,有一个问题。我们如何监控这个分离的线程,看看它是存活的还是结束了。 heartbeat 线程可能出错,对于某些系统来说,丢失 heartbeat 可能是很严重的问题。所以,我们需要跟 heartbeat 线程通信,比如通过消息流,或者条件变量。

也可以把线程的放在创建的作用域范围外,这样就一直存活。

对于以下例子

void heartbeat();

gsl::joining_thread t(heartbeat);             // heartbeat is meant to
                                              // run "forever"

heartbeat 可能会出错,然后一直运行,比如出现硬件问题。

有时候,我们需要分离创建和保管线程的时间点:

void heartbeat();

unique_ptr<gsl::joining_thread> tick_tock {nullptr};

void use()
{
    // heartbeat is meant to run as long as tick_tock lives
    tick_tock = make_unique<gsl::joining_thread>(heartbeat);
    // ...
}

强化

标记 detach()