考虑一下我有lamba foo
只做一些东西,不需要返回任何东西。
当我这样做时:
std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2);
一切运行良好,lamba将在新线程中生成。
但是,当我不存储std::future
返回的std::async
时,foo将在主线程中运行并阻止它。
std::async(std::launch::async, foo, arg1, arg2);
我在这里缺少什么?
答案 0 :(得分:17)
来自just::thread
documentation:
如果策略为
std::launch::async
,则在其自己的线程上运行INVOKE(fff,xyz...)
。当此线程完成时,返回的std::future
将变为就绪状态,并将保留函数调用抛出的返回值或异常。与返回的std::future
的异步状态关联的最后一个对象的析构函数将阻塞,直到将来准备就绪。
在
std::async(std::launch::async, foo, arg1, arg2);
返回的未来未在任何地方分配,其析构函数会阻塞,直到foo
完成。
答案 1 :(得分:4)
我想在async and ~future上添加一篇关于Herb Sutter撰写的文章的链接,其中他认为期货永远不会阻止。
答案 2 :(得分:0)
为什么要阻止?
- 立即销毁
std::async();
返回std::future
临时对象- 临时对象,并调用desctructor。
- 醇>
std::future
析构函数正在阻塞。这很糟糕也很麻烦。
为什么分配是好的?
通过分配给变量,返回的对象不会立即被销毁,但是会在以后直到销毁代码范围的末尾。
代码示例:main1
没问题。 main2
和main3
等效地阻止了主线程。
void forever() {
while (true);
}
void main1() {
std::future<void> p = std::async(std::launch::async, forever);
std::cout << "printing" << std::endl; // can print, then forever blocking
}
void main2() {
std::async(std::launch::async, forever);
std::cout << "printing" << std::endl; // forever blocking first, cannot print
}
void main3() {
{std::future<void> p = std::async(std::launch::async, forever);}
std::cout << "printing" << std::endl; // forever blocking first, cannot print
}
std :: async的返回值 选择launch :: async时,返回的future将链接到 即使从未访问过共享状态,创建的线程结束: 在这种情况下,它的析构函数与fn的返回同步。 因此,异步不应忽略返回值 行为,即使fn返回无效。