关于std :: async与std :: launch :: async参数启动的线程的混淆 [英] Confusion about threads launched by std::async with std::launch::async parameter

查看:95
本文介绍了关于std :: async与std :: launch :: async参数启动的线程的混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对std::async函数有些困惑.

该规范说:正在执行异步操作,就像在新的执行线程中一样"(C ++ 11§30.6.8/11).

The specification says: asynchronous operation being executed "as if in a new thread of execution" (C++11 §30.6.8/11).

现在,那是什么意思?

据我所知,代码

std::future<double> fut = std::async(std::launch::async, pow2, num);

应该在新线程上启动函数pow2,然后按值将变量num传递给线程,然后在将来的某个时间,当函数完成后,将结果放在fut中(只要函数pow2具有类似于double pow2(double);的签名.但是规范指出好像",这使整个事情对我来说有点模糊.

should launch the function pow2 on a new thread and pass the variable num to the thread by value, then sometime in the future, when the function is done, place the result in fut (as long as the function pow2 has a signature like double pow2(double);). But the specification states "as if", which makes the whole thing kinda foggy for me.

问题是:

在这种情况下是否总是启动新线程?我希望是这样.我的意思是,参数std::launch::async在某种意义上是有意义的,我明确表示我确实想创建一个新线程.

Is a new thread always launched in this case? I hope so. I mean for me, the parameter std::launch::async makes sense in a way that I am explicitly stating I indeed want to create a new thread.

和代码

std::future<double> fut = std::async(std::launch::deferred, pow2, num);

应该通过延迟pow2函数调用到我编写var = fut.get();之类的点来使惰性评估成为可能.在这种情况下,参数std::launch::deferred应该表示我明确地声明了,我不需要新的线程,我只是想确保在需要返回值时调用该函数.

should make lazy evaluation possible, by delaying the pow2 function call to the point where i write something like var = fut.get();. In this case the parameter std::launch::deferred, should mean that I am explicitly stating, I don't want a new thread, I just want to make sure the function gets called when there is need for it's return value.

我的假设正确吗?如果不正确,请解释.

Are my assumptions correct? If not, please explain.

此外,我知道默认情况下该函数的调用方式如下:

Also, I know that by default the function is called as follows:

std::future<double> fut = std::async(std::launch::deferred | std::launch::async, pow2, num);

在这种情况下,我被告知是否要启动新线程取决于实现.同样,这是什么意思?

In this case, I was told that whether a new thread will be launched or not depends on the implementation. Again, what is that supposed to mean?

推荐答案

std::async(<future>标头的一部分)功能模板用于启动(可能是)异步任务.它返回一个std::future对象,该对象最终将保存std::async的参数函数的返回值.

The std::async (part of the <future> header) function template is used to start a (possibly) asynchronous task. It returns a std::future object, which will eventually hold the return value of std::async's parameter function.

当需要该值时,我们在std::future实例上调用get();这将阻塞线程,直到将来准备就绪,然后返回该值.可以将std::launch::asyncstd::launch::deferred指定为std::async的第一个参数,以指定任务的运行方式.

When the value is needed, we call get() on the std::future instance; this blocks the thread until the future is ready and then returns the value. std::launch::async or std::launch::deferred can be specified as the first parameter to std::async in order to specify how the task is run.

  1. std::launch::async表示该函数调用必须在其自己的(新)线程上运行. (将用户@ T.C.的评论考虑在内).
  2. std::launch::deferred表示将在以后调用wait()get()之前推迟该函数调用.将来的所有权可以在发生这种情况之前转移到另一个线程.
  3. std::launch::async | std::launch::deferred指示实现可以选择.这是默认选项(当您自己不指定时).它可以决定同步运行.
  1. std::launch::async indicates that the function call must be run on its own (new) thread. (Take user @T.C.'s comment into account).
  2. std::launch::deferred indicates that the function call is to be deferred until either wait() or get() is called on the future. Ownership of the future can be transferred to another thread before this happens.
  3. std::launch::async | std::launch::deferred indicates that the implementation may choose. This is the default option (when you don't specify one yourself). It can decide to run synchronously.

在这种情况下是否总是启动新线程?

1.,我们可以说总是启动了一个新线程.

From 1., we can say that a new thread is always launched.

我在[std :: launch :: deferred]上的假设正确吗?

2.中,我们可以说您的假设是正确的.

From 2., we can say that your assumptions are correct.

这是什么意思? [与是否启动新线程有关,具体取决于实现方式]

来自 3.,因为std::launch::async | std::launch::deferred是默认选项,这意味着模板功能std::async的实现将决定是否创建新线程.这是因为某些实现可能正在检查过度调度.

From 3., as std::launch::async | std::launch::deferred is the default option, it means that the implementation of the template function std::async will decide whether it will create a new thread or not. This is because some implementations may be checking for over scheduling.

警告

以下部分与您的问题无关,但我认为记住这一点很重要.

The following section is not related to your question, but I think that it is important to keep in mind.

C ++标准指出,如果std::future持有对与调用异步函数相对应的共享状态的最后引用,则std :: future的析构函数必须阻塞,直到用于异步运行的函数的线程完成为止.因此,由std::async返回的std::future实例将在其析构函数中阻塞.

The C++ standard says that if a std::future holds the last reference to the shared state corresponding to a call to an asynchronous function, that std::future's destructor must block until the thread for the asynchronously running function finishes. An instance of std::future returned by std::async will thus block in its destructor.

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 ) };
}

这个令人误解的代码可以使您认为std::async调用是异步的,它们实际上是同步的.由std::async返回的std::future实例是临时的,将被阻塞,因为当std::async返回时,由于没有将其分配给变量,因此将立即调用其析构函数.

This misleading code can make you think that the std::async calls are asynchronous, they are actually synchronous. The std::future instances returned by std::async are temporary and will block because their destructor is called right when std::async returns as they are not assigned to a variable.

std::async的第一次调用将阻塞2秒,然后从第二次对std::async的调用再阻塞2秒.我们可能认为对std::async的最后一次调用不会阻塞,因为我们将其返回的std::future实例存储在变量中,但是由于这是一个在作用域末尾销毁的局部变量,因此实际上会阻塞当局部变量f被销毁时,在函数作用域的末尾又增加了2秒钟.

The first call to std::async will block for 2 seconds, followed by another 2 seconds of blocking from the second call to std::async. We may think that the last call to std::async does not block, since we store its returned std::future instance in a variable, but since that is a local variable that is destroyed at the end of the scope, it will actually block for an additional 2 seconds at the end of the scope of the function, when local variable f is destroyed.

换句话说,调用operation()函数将阻塞它同步调用的任何线程大约6秒钟.在将来的C ++标准版本中可能不存在此类要求.

In other words, calling the operation() function will block whatever thread it is called on synchronously for approximately 6 seconds. Such requirements might not exist in a future version of the C++ standard.

我用来编辑这些说明的信息来源:

C ++并发性:实用多线程,Anthony Williams

C++ Concurrency in Action: Practical Multithreading, Anthony Williams

Scott Meyers的博客文章: http://scottmeyers.blogspot.ca /2013/03/stdfutures-from-stdasync-arent-special.html

Scott Meyers' blog post: http://scottmeyers.blogspot.ca/2013/03/stdfutures-from-stdasync-arent-special.html

这篇关于关于std :: async与std :: launch :: async参数启动的线程的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆