原始C++标准仅支持单线程编程。新的C++标准(称为C++11或C++0x)于2011年发布。在C++11中,引入了新的线程库。因此运行本文程序需要C++至少符合C++11标准。

8 从线程返回值

8.1 使用说明

一个std::future对象可以与asych,std::packaged_task和std::promise一起使用。本文将主要关注将std::future与std::promise对象一起使用。很多时候,我们遇到希望线程返回结果的情况。现在的问题是如何做到这一点?

让我们举个例子假设在我们的应用程序中,我们创建了一个将压缩给定文件夹的线程,并且我们希望该线程返回新的zip文件名及其结果。现在,我们有两种方法:

使用指针在线程之间共享数据

将指针传递给新线程,此线程将设置其中的数据。在此之前,在主线程中使用条件变量继续等待。当新线程设置数据并向条件变量发送信号时,主线程将唤醒并从该指针获取数据。为了简单起见,我们使用了一个条件变量,一个互斥锁和一个指针(即3个项)来捕获返回的值。为那么问题将变得更加复杂。有没有一个简单的方法从线程返回值。答案是肯定的,使用std::future,让我们看看下一个解决方案。

C++11方式:使用std::future和std::promise

std::future是一个类模板,其对象存储将来的值。那么这future模板有什么用?实际上,一个std::future对象在内部存储了将来将分配的值,并且还提供了一种访问该值的机制,即使用get()成员函数。但是,如果有人尝试在get()函数可用之前访问future的此关联值,则get()函数将阻塞直到该值不可用。

std::promise也是一个类模板,其对象承诺将来会设置该值。每个std::promise对象都有一个关联的std::future对象,一旦std::promise对象设置了该值,它将给出该值。一个std::promise对象与其关联的std::future对象共享数据。让我们一步一步来看看,在Thread1中创建一个std::promise对象。

std::promise<int> promiseObj;

截至目前,该promise对象没有任何关联值。但是它提供了一个保证,肯定有人会在其中设置值,一旦设置了值,您就可以通过关联的std::future对象获得该值。但是现在假设线程1创建了这个promise对象并将其传递给线程2对象。现在,线程1如何知道何时线程2将在此promise对象中设置值?

答案是使用std::future对象。每个std::promise对象都有一个关联的std::future对象,其他对象可以通过该对象获取promise设置的值。

现在,线程1将把promiseObj传递给线程2。然后线程1将通过std::future的get函数获取线程2在std::promise中设置的值。

	int val = futureObj.get();

但是,如果线程2尚未设置值,则此调用将被阻塞,直到线程2在promise对象中设置值,即

	promiseObj.set_value(45);

在下图中查看完整流程:

让我们看一个完整的std::future和std::promise示例,

#include <iostream>
#include <thread>
#include <future>
void initiazer(std::promise<int> * promObj)
{
std::cout<<"Inside Thread"<<std::endl; promObj->set_value(35);
}
int main()
{
std::promise<int> promiseObj;
std::future<int> futureObj = promiseObj.get_future();
std::thread th(initiazer, &promiseObj);
std::cout<<futureObj.get()<<std::endl;
th.join();
return 0;
}

输出为:

Inside Thread
35

此外,如果您希望线程在不同的时间点返回多个值,则只需在线程中传递多个std::promise对象,然后从关联的多个std::future对象中获取多个返回值。在下一篇文章中,我们将看到如何将std::future与std::asych和std::packaged_task结合使用。

8.2 参考

https://thispointer.com//c11-multithreading-part-8-stdfuture-stdpromise-and-returning-values-from-thread/

最新文章

  1. (三)Bootstrap.jar
  2. oc-17-description
  3. (转)linux多线程,线程的分离与结合
  4. EL表达式及其定义和使用 转
  5. VB.NET 数组的定义 动态使用 多维数组
  6. 使apache解析域名到目录的方法
  7. java 静态方法和单例模式的区别
  8. [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等
  9. 解决Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/Student_recruit]]
  10. 前端笔记之JavaScript(一)初识JavaScript
  11. pylot测试工具环境搭建
  12. 关于在WP8.1中使用剪贴板的问题
  13. Webpack4 的 Tree Shaking:babel-loader设置modules: false,还是设置&quot;sideEffects&quot;: false,待确定
  14. VMWare虚拟机下为Ubuntu 12.04.1配置静态IP(NAT方式)
  15. 报错:无法将类型&quot;System.Data.EntityState&quot;隐式转换为&quot;System.Data.Entity.EntityState&quot;
  16. 第一个 Windows 界面程序
  17. [并发并行]_[线程模型]_[Pthread线程使用模型之一管道Pipeline]
  18. Sql 中取小数点后面两位小数
  19. 【BZOJ 1146】[CTSC2008]网络管理Network
  20. ubuntu 16.04 &amp;&amp; google账号问题

热门文章

  1. 动态编译库 Natasha 5.0 兼容版本发布
  2. C++和Java多维数组声明和初始化时的区别与常见问题
  3. 怎么在线预览.doc,.docx,.ofd,.pdf,.wps,.cad文件以及Office文档的在线解析方式。
  4. 解决在JS中阻止定时器“重复”开启问题、Vue中定时器的使用
  5. 二十一、Pod的存储之Secret
  6. Transformer 结构分析
  7. OpenCV图像处理与视频分析详解
  8. python中展示json数据不换行(手动换行)
  9. Java开发学习(四十)----MyBatisPlus入门案例与简介
  10. springboot前端向后端请求返回html语句