std::future::get()或std::future::wait()是std::thread::join()的替

Is std::future::get() or std::future::wait() a replacement for std::thread::join()?

本文关键字:std future join 的替 thread wait get      更新时间:2023-10-16

调用未来的future.get()/future.wait()后,线程会像thread.join()一样重新加入吗?我可以只使用线程的未来而不直接访问该线程吗?

std::future::get()std::future::wait()std::thread::join()的替代品吗

不,这些是不同的东西。

std::future是一个同步工具。它是一个的包装器,该值不是立即可用的,但会立即可用。它用于从异步操作(可以在另一个线程中运行(传递数据。在引擎盖下,它包含一个信号量,如果需要,get()会在上面等待。

另一方面,std::thread表示实际的执行线程。它可以产生多个结果,从而在其寿命期间提供多个std::promise。它应该这样做,因为启动和连接线程是一项相对繁重的操作,比等待未来要繁重得多。这就是为什么人们应该更喜欢重用线程,将异步操作发布到线程池并等待它们的结果(std::packaged_task是一个有用的抽象(。

线程不会在std::future::get()之后立即退出,即使设置promise是它所做的最后一件事。这些都是不相关的事件。

使用future时,您不能100%确定是否创建了实际的新线程。例如,当您使用std::launch::deferred执行策略创建future时,执行非常串行。

引用标准:

std::launch::deferred:任务在调用线程首次请求其结果(延迟评估(


在实践中,当您使用std::launch::async执行策略创建future时,大多数时间都会启动新线程。用gcc 10检查生成的代码,我可以清楚地看到thread::join被称为:

std::__future_base::_Async_state_commonV2::_M_complete_async():
pushq   %rbp
movq    %rsp, %rbp
//more assembly maddness
call    std::__future_base::_Async_state_commonV2::_M_join()

这又导致CCD_ 21调用。

std::__future_base::_Async_state_commonV2::_M_join():
pushq   %rbp
movq    %rsp, %rbp
subq    $48, %rsp
movq    %rdi, -40(%rbp)
movq    -40(%rbp), %rcx
addq    $32, %rcx
movq    %rcx, -24(%rbp)
movl    $std::thread::join(), %eax
...

如注释所述,std::futurestd::thread没有任何关系。因此,仅当使用std::thread时才使用std::thread::join,如果使用std::future则使用std::future::get/std::future::wait

std::future引擎盖下,有一个线程池,它接受作业并以智能的方式分发它。