std::future::get() 或 std::future::wait() 是 std::thread::join() 的替代品吗?
Is std::future::get() or std::future::wait() a replacement for std::thread::join()?
在调用了未来的 future.get()
/future.wait()
之后,线程会像 thread.join()
那样加入吗?我可以加入一个只使用它的 future 的线程而不直接访问该线程吗?
如评论中所述,std::future
与 std::thread
没有任何关系。因此,只有在使用 std::thread
时才使用 std::thread::join
,如果使用 std::future
.
,则使用 std::future::get
/std::future::wait
在 std::future
引擎盖下,有一个线程池接受作业并以智能方式分发它。
使用 future
时,您不能 100% 确定是否创建了实际的新线程。例如,当您使用 std::launch::deferred
执行策略创建 future
时,执行非常串行。
引用标准:
std::launch::deferred
: the task is executed on the calling thread the
first time its result is requested (lazy evaluation)
实际上,当您使用 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()
这又会导致 thread::join()
调用。
std::__future_base::_Async_state_commonV2::_M_join():
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movq %rdi, -40(%rbp)
movq -40(%rbp), %rcx
addq , %rcx
movq %rcx, -24(%rbp)
movl $std::thread::join(), %eax
...
Is std::future::get()
or std::future::wait()
a replacement for std::thread::join()
?
不,这些是不同的东西。
std::future
是一个同步工具。它是一个 value 的包装器,它不能立即可用,但将会可用。它用于从异步操作(可以 运行 在另一个线程中)传递数据。在引擎盖下,它包含一个信号量,如果需要,get()
会在其上等待。
另一方面,A std::thread
表示实际执行线程。它可以产生多个结果,因此在其生命周期内提供多个 std::promise
s。它应该这样做,因为启动和加入线程是一个相对重量级的操作,比等待未来要重得多。这就是为什么人们应该更喜欢重用线程,将异步操作发布到线程池并等待它们的结果(std::packaged_task
是一个有用的抽象)。
线程不会在 std::future::get()
后立即退出,即使设置 promise 是它做的最后一件事。这些是不相关的事件。
在调用了未来的 future.get()
/future.wait()
之后,线程会像 thread.join()
那样加入吗?我可以加入一个只使用它的 future 的线程而不直接访问该线程吗?
如评论中所述,std::future
与 std::thread
没有任何关系。因此,只有在使用 std::thread
时才使用 std::thread::join
,如果使用 std::future
.
std::future::get
/std::future::wait
在 std::future
引擎盖下,有一个线程池接受作业并以智能方式分发它。
使用 future
时,您不能 100% 确定是否创建了实际的新线程。例如,当您使用 std::launch::deferred
执行策略创建 future
时,执行非常串行。
引用标准:
std::launch::deferred
: the task is executed on the calling thread the first time its result is requested (lazy evaluation)
实际上,当您使用 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()
这又会导致 thread::join()
调用。
std::__future_base::_Async_state_commonV2::_M_join():
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movq %rdi, -40(%rbp)
movq -40(%rbp), %rcx
addq , %rcx
movq %rcx, -24(%rbp)
movl $std::thread::join(), %eax
...
Is
std::future::get()
orstd::future::wait()
a replacement forstd::thread::join()
?
不,这些是不同的东西。
std::future
是一个同步工具。它是一个 value 的包装器,它不能立即可用,但将会可用。它用于从异步操作(可以 运行 在另一个线程中)传递数据。在引擎盖下,它包含一个信号量,如果需要,get()
会在其上等待。
A std::thread
表示实际执行线程。它可以产生多个结果,因此在其生命周期内提供多个 std::promise
s。它应该这样做,因为启动和加入线程是一个相对重量级的操作,比等待未来要重得多。这就是为什么人们应该更喜欢重用线程,将异步操作发布到线程池并等待它们的结果(std::packaged_task
是一个有用的抽象)。
线程不会在 std::future::get()
后立即退出,即使设置 promise 是它做的最后一件事。这些是不相关的事件。