std::future and std::async 简介

Introduction

Let us consider a simple thing: use some worker thread to compute a value. In the source code, it can look like that:

让我们思考一个简单的事情:使用一些工作线程来计算一些数值。源代码看起来如下:

std::thread t([]() { auto res = perform_long_computation(); });

We would like to obtain the result when it is completed of course. But how to do it efficiently?

当计算完成,我们想获取结果。但怎么有效的做到呢?

A shared variable can be used:

可以使用共享变量:

MyResult sharedRes;
std::thread t([&]() { sharedRes = perform_long_computation(); });

But that way, we need to know that the thread t is finished and sharedRes contain computed value; A lot of constructions can be used here: atomics, mutexes, condition variables, etc. but maybe there is a better and simpler way of doing that? 

但是这种方式,我们需要知道线程t已经完成,并且sharedRes包含计算结果;这儿有许多构造可用,原子操作,互斥量,条件变量等,或许这里可以有一个简单并更好的方式。

Let us have a look at this code:

让我们看看下面的代码:

auto result = std::async([]() { return perform_long_computation(); });
MyResult finalResult = result.get();

Isn't that simpler? But what actually happened there?

是不是更简单?但是这儿究竟做了什么?

The Future

In C++11 in the Standard Library, we have all sorts of concurrency features. As usual, we have threads, mutexes, atomics, etc. Fortunately for us, the library went further and added some higher level structures. In our example, we need to look at future and async.

在C++11的标准库中,我们有所有种类的并发特性。通常,我们有线程,互斥量,原子等。我们很幸运,标准库做了更多,一些高级结构也被加进来了。在我们的例子里,我们需要关注future和async。

If we do not want to get into much details, all we need to know is that std::future<T> holds a shared state and std::async allow us to run the code asynchronously. In our case, we can rewrite it to:

如果我们不想了解太多细节,我们仅需要知道std::future<T>拥有一个共享状态,而std::async允许我们异步执行代码。我们可以重写上面的例子:

std::future<MyResult> result = std::async([]() { return perform_long_computation(); });
MyResult finalResult = result.get();

Thus result is not a direct value computed in the thread but it is some form of a guard that makes sure the value is ready when we call .get() method. All the magic (synchronization) happens underneath. Often it will simply block the calling thread and wait for the data (or exception). 

如此,result就不是直接在线程里计算的值,但是它具有一种形式的保护来确保当我们调用.get()方法的时候这个值是可用的。所有的魔法(同步)发生在这之下。通常它会阻塞调用线程等待数据可用(或者异常发生)。

This opens some interesting possibilities and we can start with Task Based Parallelism. We can now build some form of a pipeline where data flows from one side to the other, but in the middle computation can be distributed among several threads. Such constructions definitely deserve more investigation!

这样就有一些有趣的可能性出现,我们可以开始基于任务的并行性。我们现在可以构建一种形式的管道,让数据从一端流向另一端,在这中间,计算可以散布到多个线程中。这样的构造确实值得研究。

Below, there is a simple idea of the mentioned approach: you divide your computation into several separate parts, call them asynchronously and at the end collect the final result. It is up to the system/library to decide if each part is called on a dedicated thread (if available), or just run it on only one thread. This makes the solution more scalable.

下面是对前述的方法的简单想法:你把你的计算拆分为几个单独的部分,异步的调用它们,在最后收集最终的计算结果。由系统/标准库来决定各个单独的计算是由各自的专用线程(如果可用)调用还是全部都在一个线程中执行。这样的方案有良好的伸缩性。

【图片加载失败】

Notes

  • .get() can be called only once! The second time we will get exception. If you want to fetch the result from several threads or several times in single thread, you can use std::shared_future.
  • .get() 只能被调用一次。第二次调用会得到异常。如果你想在多个线程中取得结果,或者在一个线程中取得多次结果,你可以使用 std::shared_future.
  • std::async can run code in the same thread as the caller. Launch Policy can be used to force truly asynchronous call - std::launch::async or std::launch::deferred
  • std::async 可以在和调用者的同一线程中执行。可以使用启动策略强制执行异步调用 - std::launc::async 或者 std::launch::deferred。
  • when there is an exception in the future (inside our lambda or function), this exception will be propagated and rethrown in the .get() method.
  • 当有异常在std::future中产生(在lambda或函数中),这个异常会被传播并在.get()方法中重新抛出。

References

  • See The C++ Standard Library: A Tutorial and Reference (2nd Edition), chapter 18.1 for a great introduction to the concurrency in std.
  • See The C++ Programming Language, 4th Edition , chapter 41
  • C++ Concurrency in Action: Practical Multithreading

History

  • 14th October 2014 - added an image with Task Based Parallelism idea
  • 20th January 2014 - minor changes 
  • 17th January 2014 - Initial version 

Tip based on the original post at my site.

&lt;a href="http://ad.doubleclick.net/N6839/jump/lqm.codeproject.site/Languages/C-Cplusplus-Language/Beginners;sz=300x250;ord=635492253575602000?"&gt;&lt;img src="http://ad.doubleclick.net/N6839/ad/lqm.codeproject.site/Languages/C-Cplusplus-Language/Beginners;sz=300x250;ord=635492253575602000?" width="300px" height="250px" /&gt;&lt;/a&gt;

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



原文地址

http://www.codeproject.com/Tips/712107/Simple-introduction-to-std-future-and-std-async



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值