调用thread.join()
/ future.get()
以后获得的收益后,线程会像future.wait()
一样联接吗?我可以仅在将来使用线程而不直接访问该线程吗?
答案 0 :(得分:2)
std::future::get()
或std::future::wait()
可以代替std::thread::join()
吗?
不,这些是不同的东西。
std::future
是一个同步工具。它是围绕 value 的包装,该包装不是立即可用,而是将可用。它用于通过异步操作(可以在另一个线程中运行)传递数据。在引擎盖下包含一个信号灯,如有需要,get()
在上面等待。
另一方面,std::thread
代表实际的执行线程。它可以产生多个结果,从而在其生命周期内提供多个std::promise
。应该这样做,因为启动和加入线程是一项相对繁重的操作,比等待未来要重得多。这就是为什么应该更喜欢重用线程,将异步操作发布到线程池并等待其结果的原因(std::packaged_task
是对此的一种有用的抽象)。
在std::future::get()
之后,即使设置promise是它所做的最后一件事情,线程也不会立即退出。这些是无关的事件。
答案 1 :(得分:1)
如评论中所述,Link
与std::future
没有任何关系。因此,仅在使用std::thread
时使用std::thread::join
,如果使用std::thread
则使用std::future::get
/ std::future::wait
。
在std::future
内部,有一个线程池可以接受作业并以一种聪明的方式分配它。
答案 2 :(得分:1)
在使用future
时,您不能100%确定是否创建了实际的新线程。例如,当您使用future
执行策略创建std::launch::deferred
时,执行是非常串行的。
引用标准:
std::launch::deferred
:任务在调用线程上执行 第一次请求其结果(延迟评估)
实际上,大多数时候在启动新线程时使用future
执行策略创建std::launch::async
时。用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()
依次导致thread::join()
调用。
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
...