详解C++中future和promise的使用

 更新时间:2023年05月30日 11:16:25   作者:PKICA  
future和promise的作用是在不同线程之间传递数据,这篇文章主要为大家详细介绍了C++中future和promise的具体使用,感兴趣的小伙伴可以跟随小编一起学习一下

future和promise的作用是在不同线程之间传递数据。使用指针也可以完成数据的传递,但是指针非常危险,因为互斥量不能阻止指针的访问;而且指针的方式传递的数据是固定的,如果更改数据类型,那么还需要更改有关的接口,比较麻烦;promise支持泛型的操作,更加方便编程处理。

假设线程1需要线程2的数据,那么组合使用方式如下:

线程1初始化一个promise对象和一个future对象,promise传递给线程2,相当于线程2对线程1的一个承诺;future相当于一个接受一个承诺,用来获取未来线程2传递的值

线程2获取到promise后,需要对这个promise传递有关的数据,之后线程1的future就可以获取数据了。

如果线程1想要获取数据,而线程2未给出数据,则线程1阻塞,直到线程2的数据到达

future对象是std::async、std::promise、std::packaged_task的底层对象,用来传递其他线程中操作的数据结果。

std::promise的作用就是提供一个不同线程之间的数据同步机制,它可以存储一个某种类型的值,并将其传递给对应的future, 即使这个future不在同一个线程中也可以安全的访问到这个值。

/** @file  20190815future.cpp
*  @note  
*  @brief
*  @author 
*  @date   2019-8-15
*  @note   
*  @history
*  @warning
*/
#include <iostream>
#include <functional>
#include <future>
#include <thread>
#include <chrono>
#include <cstdlib>

void thread_set_promise(std::promise<int>& promiseObj) {
    std::cout << "In a thread, making data...\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    promiseObj.set_value(35);
    std::cout << "Finished\n";
}

int main() {
    std::promise<int> promiseObj;
    std::future<int> futureObj = promiseObj.get_future();
    std::thread t(&thread_set_promise, std::ref(promiseObj));
    std::cout << futureObj.get() << std::endl;
    t.join();

    system("pause");
    return 0;
}

async(高级封装future和thread)

std::future可以从异步任务中获取结果,一般与std::async配合使用,std::async用于创建异步任务,实际上就是创建一个线程执行相应任务。

std::async就是异步编程的高级封装,封装了std::future的操作,基本上可以代替std::thread 的所有事情。

std::async的操作,其实相当于封装了std::promise、std::packaged_task加上std::thread。

/** @file  futureIsPrime.cpp
*  @note   
*  @brief
*  @author 
*  @date   2019-8-15
*  @note   
*  @history
*  @warning
*/
// future example
#include <iostream>       // std::cout
#include <future>         // std::async, std::future
#include <chrono>         // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

int main ()
{
  // call function asynchronously:
  std::future<bool> fut = std::async (is_prime,444444443);

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.' << std::flush;

  bool x = fut.get();     // retrieve return value

  std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

std::async会首先创建线程执行is_prime(444444443), 任务创建之后,std::async立即返回一个std::future对象。

主线程既可使用std::future::get获取结果,如果调用过程中,任务尚未完成,则主线程阻塞至任务完成。

主线程也可使用std::future::wait_for等待结果返回,wait_for可设置超时时间,如果在超时时间之内任务完成,则返回std::future_status::ready状态;如果在超时时间之内任务尚未完成,则返回std::future_status::timeout状态。

std::packaged_task用法

std::packaged_task的作用就是提供一个不同线程之间的数据同步机制,它可以存储一个函数操作,并将其返回值传递给对应的future, 而这个future在另外一个线程中也可以安全的访问到这个值。

// packaged_task example
#include <iostream>     // std::cout
#include <future>       // std::packaged_task, std::future
#include <chrono>       // std::chrono::seconds
#include <thread>       // std::thread, std::this_thread::sleep_for

// count down taking a second for each value:
int countdown (int from, int to) {
  for (int i=from; i!=to; --i) {
    std::cout << i << '\n';
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  std::cout << "Lift off!\n";
  return from-to;
}

int main ()
{
  std::packaged_task<int(int,int)> tsk (countdown);   // set up packaged_task
  std::future<int> ret = tsk.get_future();            // get future

  std::thread th (std::move(tsk),10,0);   // spawn thread to count down from 10 to 0

  // ...

  int value = ret.get();                  // wait for the task to finish and get result

  std::cout << "The countdown lasted for " << value << " seconds.\n";

  th.join();

  return 0;
}

到此这篇关于详解C++中future和promise的使用的文章就介绍到这了,更多相关C++ future promise内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 完全掌握C++编程中构造函数使用的超级学习教程

    完全掌握C++编程中构造函数使用的超级学习教程

    这篇文章主要介绍了C++中的构造函数,包括C++11标准中的新特性的介绍,十分推荐!需要的朋友可以参考下
    2016-01-01
  • MySQL的内存表的基础学习教程

    MySQL的内存表的基础学习教程

    这篇文章主要介绍了MySQL的内存表的基础学习教程,包括内存表的创建以及使用限制等等,需要的朋友可以参考下
    2015-12-12
  • C语言转义字符详解

    C语言转义字符详解

    这篇文章主要介绍了C语言转义字符详解,本篇文章通过简要的案例,讲解了C语言转义字符该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++简单集合类的实现方法

    C++简单集合类的实现方法

    如何使用C++实现一个简单的集合类,这篇文章主要介绍了C++简单集合类的实现方法,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • C语言修炼之路初识分支句 循环助本心下篇

    C语言修炼之路初识分支句 循环助本心下篇

    现实生活中我们经常需要根据不同的条件做出不同的选择。程序设计中也需要根据条件来选择不同的程序进行处理,这称之为分支结构,当条件表达式不存在时,它被假设为真。您也可以设置一个初始值和增量表达式,一般情况下,C 程序员偏向于使用 for(;;) 结构来表示一个无限循环
    2022-03-03
  • C++多线程与锁机制使用解读

    C++多线程与锁机制使用解读

    文章主要介绍了C++中的多线程编程知识,包括线程的创建、参数传递、线程休眠、互斥锁、条件变量、原子操作、死锁预防、线程局部存储、读写锁和自旋锁等内容,并给出了相应的实现方法和使用场景
    2026-04-04
  • c++实现LinkBlockedQueue的问题

    c++实现LinkBlockedQueue的问题

    这篇文章主要介绍了c++实现LinkBlockedQueue的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • C++数据精度问题(对浮点数保存指定位小数)

    C++数据精度问题(对浮点数保存指定位小数)

    这篇文章主要介绍了对浮点数保存指定位小数。比如, 1.123456. 要保存1位小数,,调用方法后, 保存的结果为: 1.1。 再比如,1.98765, 保存2位小数的结果为: 2.00,需要的朋友可以参考下
    2017-08-08
  • C语言中pow函数使用方法、注意事项以及常见报错原因

    C语言中pow函数使用方法、注意事项以及常见报错原因

    在c语言当中我们要计算一个数的n次方时候,可以使用多种方法,但是也有一种比较简单的方法,便是调用一个函数pow函数,下面这篇文章主要给大家介绍了关于C语言中pow函数使用方法、注意事项以及常见报错原因的相关资料,需要的朋友可以参考下
    2022-11-11
  • C++ Vector用法详解

    C++ Vector用法详解

    这篇文章主要介绍了C++ Vector用法详解,vector是C++标准模版库(STL,Standard Template Library)中的部分内容,本文详细介绍了它的方方面面,需要的朋友可以参考下
    2015-07-07

最新评论