C++ 关于std::async与std::launch::async参数启动的线程的混淆
我对C++ 关于std::async与std::launch::async参数启动的线程的混淆,c++,multithreading,c++11,future,stdthread,C++,Multithreading,C++11,Future,Stdthread,我对std::async函数有点困惑 说明书上说: 异步操作“如同在新的执行线程中”执行(C++11§30.6.8/11) 那是什么意思 据我所知,代码 std::future fut=std::async(std::launch::async,pow2,num); 应该在新线程上启动函数pow2,并通过值将变量num传递给线程,然后在将来某个时候,当函数完成时,将结果放入fut(只要函数pow2具有类似double pow2(double);)的签名)。但是说明书上写着“好像”,这让我觉得整
std::async
函数有点困惑
说明书上说:
异步操作“如同在新的执行线程中”执行(C++11§30.6.8/11)
那是什么意思
据我所知,代码
std::future fut=std::async(std::launch::async,pow2,num);
应该在新线程上启动函数pow2
,并通过值将变量num
传递给线程,然后在将来某个时候,当函数完成时,将结果放入fut
(只要函数pow2
具有类似double pow2(double);
)的签名)。但是说明书上写着“好像”,这让我觉得整个事情有点模糊不清
问题是:
在这种情况下总是启动新线程吗?我希望如此。我的意思是,对于我来说,参数std::launch::async
在某种程度上是有意义的,因为我明确表示我确实想要创建一个新线程
代码呢
std::future fut=std::async(std::launch::deferred,pow2,num);
应该通过将pow2
函数调用延迟到我编写类似var=fut.get()之类的代码的点,使延迟求值成为可能代码>。在本例中,参数std::launch::deferred
,应该意味着我要明确声明,我不想要新线程,我只想确保在需要函数返回值时调用该函数
我的假设正确吗?如果不正确,请解释
另外,我知道默认情况下,函数的调用方式如下:
std::future fut=std::async(std::launch::deferred | std::launch::async,pow2,num);
在本例中,我被告知是否启动新线程取决于实现。同样,这意味着什么?使用std::async
(
标题的一部分)函数模板来启动(可能的)异步任务。它返回一个std::future
对象,该对象最终将保存std::async
的参数函数的返回值
当需要该值时,我们在std::future
实例上调用get();这将阻塞线程,直到将来准备就绪,然后返回值std::launch::async
或std::launch::deferred
可以指定为std::async
的第一个参数,以指定任务的运行方式
std::launch::async
表示函数调用必须在其自己的(新)线程上运行。(考虑用户@T.C.的评论)
std::launch::deferred
表示函数调用将被延迟,直到将来调用wait()
或get()
。在这种情况发生之前,未来的所有权可以转移到另一个线程
std::launch::async | std::launch::deferred
表示实现可以选择。这是默认选项(当您自己没有指定一个选项时)。它可以决定同步运行
在这种情况下总是启动新线程吗?
从1.,我们可以说总是启动一个新线程
我的假设[关于标准::启动::延期]正确吗?
从2.,我们可以说您的假设是正确的
这是什么意思?[与正在启动或未启动的新线程相关,取决于实现]
从3.开始,由于std::launch::async | std::launch::deferred
是默认选项,这意味着模板函数std::async
的实现将决定是否创建新线程。这是因为一些实现可能正在检查过度调度
警告
以下部分与你的问题无关,但我认为记住这一点很重要
C++标准称如果<代码> STD::将来< /C>保留与异步函数调用对应的共享状态的最后引用,则STD::Engor的析构函数必须阻塞,直到异步运行函数的线程结束。因此,由
std::async
返回的std::future
实例将在其析构函数中阻塞
void operation()
{
auto func = [] { std::this_thread::sleep_for( std::chrono::seconds( 2 ) ); };
std::async( std::launch::async, func );
std::async( std::launch::async, func );
std::future<void> f{ std::async( std::launch::async, func ) };
}
void操作()
{
auto-func=[]{std::this_thread::sleep_for(std::chrono::seconds(2));};
std::async(std::launch::async,func);
std::async(std::launch::async,func);
std::future f{std::async(std::launch::async,func)};
}
这种误导性的代码会让您认为std::async
调用是异步的,实际上是同步的。由std::async
返回的std::future
实例是临时的,并且将被阻止,因为当std::async
返回时,它们的析构函数被正确调用,因为它们没有分配给变量
对std::async
的第一次调用将阻塞2秒,然后从对std::async
的第二次调用开始再阻塞2秒。我们可能认为对std::async
的最后一次调用不会阻塞,因为我们将其返回的std::future
实例存储在一个变量中,但由于它是一个局部变量,在作用域结束时被销毁,它实际上会在函数作用域结束时阻塞额外的2秒钟,当局部变量f被破坏时
换句话说,调用operation()
函数将同步阻止调用它的任何线程大约6秒钟。在C++标准的未来版本中可能不存在这样的要求。
我过去编译的信息来源
#include <future>
#include <thread>
#include <iostream>
using namespace std;
int main()
{
cout << "main thread id " << this_thread::get_id() << endl;
future<int> f1 = async(launch::async, [](){
cout << "future run on thread " << this_thread::get_id() << endl;
return 1;
});
f1.get();
future<int> f2 = async(launch::async, [](){
cout << "future run on thread " << this_thread::get_id() << endl;
return 1;
});
f2.get();
future<int> f3 = async(launch::async, [](){
cout << "future run on thread " << this_thread::get_id() << endl;
return 1;
});
f3.get();
cin.ignore();
return 0;
}
main thread id 4164
future run on thread 4188
future run on thread 4188
future run on thread 4188