您是否需要存储来自 std::async 的 std::future return 值?
Do you need to store the std::future return value from std::async?
考虑以下代码:
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
void func()
{
std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
}
int main()
{
std::cout << "start " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
func();
std::cout << "stop " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
return 0;
}
输出:
start 18737230ms
stop 18738230ms
我们可以看到 func()
returns 前 1 秒过去了。但是 std::async(...);
中没有存储 std::future - 即:auto f = std::async(...)
这似乎有效 - 但我正在徘徊是什么机制使它有效。如果我有一个 std::future(在我的小例子中是 auto f),那么当它超出范围时,它会整理线程——即等待 1 秒,然后线程在幕后被处理掉。
进一步测试:
int main() {
std::cout << "start " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
std::cout << "stop1 " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
auto f = std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
std::cout << "stop2 " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
return 0;
}
给出:
start 4448133ms
stop1 4449133ms - 1 sec passed
stop2 4449133ms - no time passed
所以这表明存储未来意味着线程 运行 是并行的。不存储未来意味着线程似乎必须 运行 完成 - 我猜这是因为创建和销毁了一个临时的未来?
所以我的结论是,如果你想让它并行地 运行(这就是重点),你不能只调用 std::async(...)
而不存储 std::future - 即使如果您不打算使用未来。
嗯...我想我刚刚说服自己回答了这个问题! - 但我不是 100% 确定我的推理是正确的 - 希望我有...
如果std::future
是通过std::async
创建的,析构函数等待任务结束。这并不意味着该任务不会 运行 并行 - 它只是等待变量范围末尾的任务结束。然而,它在不存储 std::future
的情况下使用 std::async
有点棘手,我通常建议将未来存储在某个地方以避免令人讨厌的意外。看看at page about std::future
destructor(强调我的):
these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state.
考虑以下代码:
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
void func()
{
std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
}
int main()
{
std::cout << "start " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
func();
std::cout << "stop " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
return 0;
}
输出:
start 18737230ms
stop 18738230ms
我们可以看到 func()
returns 前 1 秒过去了。但是 std::async(...);
中没有存储 std::future - 即:auto f = std::async(...)
这似乎有效 - 但我正在徘徊是什么机制使它有效。如果我有一个 std::future(在我的小例子中是 auto f),那么当它超出范围时,它会整理线程——即等待 1 秒,然后线程在幕后被处理掉。
进一步测试:
int main() {
std::cout << "start " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
std::cout << "stop1 " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
auto f = std::async(std::launch::async, []{std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
std::cout << "stop2 " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count() << "ms\n";
return 0;
}
给出:
start 4448133ms
stop1 4449133ms - 1 sec passed
stop2 4449133ms - no time passed
所以这表明存储未来意味着线程 运行 是并行的。不存储未来意味着线程似乎必须 运行 完成 - 我猜这是因为创建和销毁了一个临时的未来?
所以我的结论是,如果你想让它并行地 运行(这就是重点),你不能只调用 std::async(...)
而不存储 std::future - 即使如果您不打算使用未来。
嗯...我想我刚刚说服自己回答了这个问题! - 但我不是 100% 确定我的推理是正确的 - 希望我有...
如果std::future
是通过std::async
创建的,析构函数等待任务结束。这并不意味着该任务不会 运行 并行 - 它只是等待变量范围末尾的任务结束。然而,它在不存储 std::future
的情况下使用 std::async
有点棘手,我通常建议将未来存储在某个地方以避免令人讨厌的意外。看看at page about std::future
destructor(强调我的):
these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state.