原始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/

[编程基础] C++多线程入门8-从线程返回值的更多相关文章

  1. [编程基础] C++多线程入门1-创建线程的三种不同方式

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

  2. [编程基础] C++多线程入门4-数据共享和资源竞争

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

  3. [编程基础] C++多线程入门7-条件变量介绍

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

  4. [编程基础] C++多线程入门10-packaged_task示例

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

  5. [编程基础] C++多线程入门9-async教程和示例

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

  6. [编程基础] C++多线程入门3-小心地将参数传递给线程

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

  7. [编程基础] C++多线程入门2-连接和分离线程

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

  8. [编程基础] C++多线程入门6-事件处理的需求

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

  9. [编程基础] C++多线程入门5-使用互斥锁解决资源竞争

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

随机推荐

  1. SQL抽象语法树及改写场景应用

    1 背景 我们平时会写各种各样或简单或复杂的sql语句,提交后就会得到我们想要的结果集.比如sql语句,"select * from t_user where user_id > 10 ...

  2. Vue学习之--------插槽【默认插槽、具名插槽、作用域插槽】(2022/8/30)

    插槽Vue.js官网介绍:https://vuejs.org/guide/components/slots.html 会牵涉到template的用法.占位.实际不渲染到页面中 1.默认插槽: 1.1 ...

  3. 创建Vue工程常用的命令

    创建一个vue项目的步骤 1.创建一个名称为myapp的工程 vue init webpack myapp 2.进入工程目录 cd myapp 3.安装 vue-router npm install ...

  4. 如何在IDEA中自定义模板、快速生成完整的代码?

    文章目录 1.修改现有的模板 2.自定义模板 3.在代码中测试自定义模板 1.修改现有的模板 打开设置面板- settings 2.自定义模板 选择定义模板组 选择创建模板 define 代表应用的范 ...

  5. 二、Kubernetes 概念介绍

    一.Master ​ Master指的是集群控制节点,在每个Kubernetes集群里都需要有一个Master来负责整个集群的管理和控制,基本上Kubernetes的所有控制命令都发给它,它负责具体的 ...

  6. 云原生之旅 - 5)Kubernetes时代的包管理工具 Helm

    前言 上一篇文章 [基础设施即代码 使用 Terraform 创建 Kubernetes] 教会了你如何在Cloud上面建Kubernetes资源,那么本篇来讲一下如何在Kubernetes上面部署应 ...

  7. 浅入浅出 1.7和1.8的 HashMap

    前言 HashMap 是我们最最最常用的东西了,它就是我们在大学中学习数据结构的时候,学到的哈希表这种数据结构.面试中,HashMap 的问题也是常客,现在卷到必须答出来了,是必须会的知识. 我在学习 ...

  8. Ubuntu安装Docker及镜像加速器

    一.安装Docker sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificate ...

  9. 类视图函数 VIEW

    常用的视图函数: ListView.DetailView.UpdateView 1 ListView object_list:此属性表示对象的列表 常用场景: 1.展示数据库中信息: 2.在展示信息时 ...

  10. C#一个16进制数用二进制数表示是几位?

    1个字节是8位,二进制8位:xxxxxxxx 范围从00000000-11111111,表示0到255.一位16进制数(用二进制表示是xxxx) 最多只表示到15(即对应16进制的F),要表示到255 ...