原始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. 图解 | 聊聊 MyBatis 缓存

    首发公众号-悟空聊架构:图解 | 聊聊 MyBatis 缓存 你好,我是悟空. 本文主要内容如下: 一.MyBatis 缓存中的常用概念 MyBatis 缓存:它用来优化 SQL 数据库查询的,但是可 ...

  2. Springboot JSON 转换:Jackson篇

    本案例基于 Springboot 2.5.7 单元测试场景下进行 <!-- SpringMVC默认使用Jacson,只需要引用web启动器即可,无序单独引用Jackson --> < ...

  3. 四、Django中使用celery

    项目跟目录创建celery包,目录结构如下: mycelery/ ├── config.py ├── __init__.py ├── main.py └── sms/ ├── __init__.py ...

  4. Day14 note1

    package com.oop.demo06;public class Person { public void run(){ System.out.println("run"); ...

  5. OpenFOAM 编程 | 求解捕食者与被捕食者模型(predator-prey model)问题(ODEs)

    0. 写在前面 本文问题参考自文献 \(^{[1]}\) 第一章例 6,并假设了一些条件,基于 OpenFOAM-v2206 编写程序数值上求解该问题.笔者之前也写过基于 OpenFOAM 求解偏分方 ...

  6. Oracle收集统计信息的一些思考

    一.问题 Oracle在收集统计信息时默认的采样比例是DBMS_STATS.AUTO_SAMPLE_SIZE,那么AUTO_SAMPLE_SIZE的值具体是多少? 假设采样比例为10%,那么在计算单个 ...

  7. Jmeter添加性能监控插件监控被测系统资源

    使用jmeter来监控服务器资源(CPU.I/O.内存.网络等),需要安装jmeter性能监控插件以及在被测服务器中启动监控服务. 一.下载并安装插件 下载 Plugins Manager插件管理器, ...

  8. 16.python中的回收机制

    python中的垃圾回收机制是以引用计数器为主,标记清除和分代回收为辅的 + 缓存机制 1.引用计数器 在python内部维护了一个名为refchain的环状双向链表,在python中创建的任何对象都 ...

  9. 嵌入式-C语言基础:数组得初始化

    #include<stdio.h> int main() { int a[10]; int size=sizeof(a)/sizeof(a[0]);//计算数组得大小 for(int i= ...

  10. 数据结构篇——KMP算法

    数据结构篇--KMP算法 本次我们介绍数据结构中的KMP算法,我们会从下面几个角度来介绍: 问题介绍 暴力求解 知识补充 Next示例 Next代码 匹配示例 匹配代码 完整代码 问题介绍 首先我们先 ...