C++11获取线程返回值的实现代码

 更新时间:2019年04月07日 20:14:39   投稿:mdxy-dxy  
这篇文章主要介绍了C++11获取线程返回值的实现代码,需要的朋友可以参考下

C++11 std::future and std::promise
在许多时候,我们会有这样的需求——即我们想要得到线程返回的值。
但是在C++11 多线程中我们注意到,std::thread对象会忽略顶层函数的返回值。
那问题来了,我们要怎么获得线程的返回值呢?

我们通过一个例子来说明如何实现这个需求。

假设我们的app会创建一个线程来压缩一个文件夹,该线程在压缩完文件夹后会返回压缩文件 *.zip 和这个zip文件的大小,我们现在就想获得这个线程的返回值。

有两种方法可以实现这个需求:

1. 传统的方法:在线程间共享指针

传递一个指针给压缩文件的线程,表示压缩文件的线程将会把值写入指针指向的内存空间。此时主线程将用条件变量等待值被写入,当压缩文件线程把值写入指针指定的内存后,将唤醒(signal)条件变量,然后主线程将被唤醒,然后从指针指向的内存中获取返回值。

为了实现获取一个返回值的需求,使用传统的方法,我们需要条件变量(condition variable), 互斥量(mutex),和指针三个对象。
如果假设,我们需要获得压缩线程里三个返回值,情况会变得更加复杂。

那std::future就是来简化这个编程过程的

2. C++11的方法:使用std::future和std::promise

人如其名,std::futurestd::promise对象就和他们的名字一样。这两个类在获取程序返回值的时候需要配合使用

std::future,是一个类模板,它存储着一个未来的值。
那问题来了,未来的值是什么鬼?

实际上一个std::future对象里存储着一个在未来会被赋值的变量,这个变量可以通过std::future提供的成员函数std::future::get()来得到。如果在这个变量被赋值之前就有别的线程试图通过std::future::get()获取这个变量,那么这个线程将会被阻塞到这个变量可以获取为止。

std::promise同样也是一个类模板,它的对象承诺会在未来设置变量(这个变量也就是std::future中的变量)。每一个std::promise对象都有一个与之关联的std::future对象。当std::promise设置值的时候,这个值就会赋给std::future中的对象了。

我们一步一步来看一下如何做

在主线程中创建std::promise对象

std::promise<int> promiseObj;

上面定义的promise对象还没有任何关联的值。但是它承诺某个线程将会设置与其关联的值,并且,当值被设置以后,可以通过与promise关联的std::future对象来获取该值。

假设我们的主线程将创建的std::promise对象传递给了压缩线程,那主线程要怎么知道压缩线程已经设置好了值呢?
答案就是使用 std::future对象

// main thread
std::future<int> futureObj = promiseObj.get_future();
int val = futureObj.get();

// compression thread
promiseObj.set_value(45);

在compression thread未执行set_value()时,如果主线程调用了futureObj.get(),那么主线程将会被阻塞。

看整个时序图:

最终代码

#include<iostream>  //std::cout std::endl
#include<thread>   //std::thread
#include<future>   //std::future std::promise
#include<utility>   //std::ref
#include<chrono>   //std::chrono::seconds

void initiazer(std::promise<int> &promiseObj){
  std::cout << "Inside thread: " << std::this_thread::get_id() << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(1));
  promiseObj.set_value(35);
}

int main(){
  std::promise<int> promiseObj;
  std::future<int> futureObj = promiseObj.get_future();
  std::thread th(initiazer, std::ref(promiseObj));
  
  std::cout << futureObj.get() << std::endl;

  th.join();
  return 0;
}

本文参考于C++11 Multithreading – Part 8: std::future , std::promise and Returning values from Thread,并做了适当修改

相关文章

  • Linux下C语言的fork()子进程函数用法及相关问题解析

    Linux下C语言的fork()子进程函数用法及相关问题解析

    fork()函数在Linux下可以用于产生一个子进程,这里我们挑选了两个fork相关的面试题,来看一下Linux下C语言的fork()子进程函数用法及相关问题解析
    2016-06-06
  • C++中指针和引用的区别详解

    C++中指针和引用的区别详解

    这篇文章主要介绍了C++中指针和引用的区别详解的相关资料,需要的朋友可以参考下
    2017-02-02
  • C++程序的执行顺序结构以及关系和逻辑运算符讲解

    C++程序的执行顺序结构以及关系和逻辑运算符讲解

    这篇文章主要介绍了C++程序的执行顺序结构以及关系和逻辑运算符讲解,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • 举例讲解C语言链接器的符号解析机制

    举例讲解C语言链接器的符号解析机制

    链接器的工作主要分为两个阶段:符号解析和重定位,符号解析的功能是将每个模块符号引用绑定到一个确切的符号定义,这里我们就来举例讲解C语言链接器的符号解析机制
    2016-05-05
  • C++中typedef 及其与struct的结合使用

    C++中typedef 及其与struct的结合使用

    这篇文章主要介绍了C++中typedef 及其与struct的结合使用,需要的朋友可以参考下
    2014-02-02
  • QT自定义之滑动开关

    QT自定义之滑动开关

    这篇文章主要为大家详细介绍了QT自定义之滑动开关效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • 如何在 C++ 中实现一个单例类模板

    如何在 C++ 中实现一个单例类模板

    这篇文章主要介绍了如何在 C++ 中实现一个单例类模板,帮助大家更好的理解和学习c++编程,感兴趣的朋友可以了解下
    2020-10-10
  • C++11中lambda、std::function和std:bind详解

    C++11中lambda、std::function和std:bind详解

    大家都知道C++11中增加了许多的新特性,下面在这篇文中我们就来聊一下lambda表达式,闭包,std::function以及std::bind。文中介绍的很详细,相信对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。
    2017-01-01
  • C++使用sort对容器排序的实现

    C++使用sort对容器排序的实现

    C++ STL 标准库中的sort()函数专门用来对容器或普通数组中指定范围内的元素进行排序,本文就详细的介绍一下怎么实现,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • MFC程序执行过程深入剖析

    MFC程序执行过程深入剖析

    这篇文章主要介绍了MFC程序执行过程,包括对MFC执行流程的分析以及断点调试分析出的SDI程序执行流程,需要的朋友可以参考下
    2014-09-09

最新评论