文章目录

  • future前言
  • future描述
  • future类成员使用
  • 总结

future前言

首先查看如下代码

#include <iostream>
#include <thread>
#include <future>
#include <mutex>using namespace std;void fun1(int n,int &x) {int res = 1;for (int i = n; i>1; --i) {res *=i;}cout << "Result is " << res << endl;//输出最终的结果并赋值给共享变量xx = res;
}int main()
{int x;std::thread t1(fun1,4,std::ref(x));t1.join();return 0;
}

这段代码仅拥有一个线程,但是可以很明显得看到主线程和t1线程想要共享同一个变量x,同时x是需要在t1线程进行赋值将结果返回给主线程,由主线程来获取。这样的线程之间的变量传递,我们所知道的传递方式只能是传递引用。同时仅仅传递引用是不够的,因为线程之间的变量共享需要对变量进行保护才能安全有效共享,这样就需要引入mutex互斥变量和condition_variable条件变量对共享变量进行保护。

这样会导致代码逻辑更加复杂,逻辑细节也会变得非常谨慎。这个时候我们引入future类对以上操作进行简化。

future描述

  • 头文件 <future>
  • 声明template< class T > class future<T&>;
  • 简介
    future类模版提供了一种异步访问操作机制如下:

    • 异步操作能提供一个 std::future 对象给该异步操作的创建者。其中包括std::asyncstd::packaged_taskstd::promise的返回值为std::future对象
    • 异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。如使用std::async创建的异步操作返回的future对象未获取值,那么std::async将不会退出
    • 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如std::promise::set_value)进行

future类成员使用

  • std::future<T>::get 获取异步操作的返回结果
    get 方法等待直至 future 拥有合法结果并(依赖于使用哪个模板)获取它。它等效地调用 wait() 等待结果
    这里需要简单说明下get函数的返回值,它的返回值为std::move()类型,即将之前的返回结果包括值和地址都进行赋值。如果二次尝试get,回访问到空的值和地址,报出异常std::future_error
    我们对刚开始的代码更改如下:

    #include <iostream>
    #include <thread>
    #include <future>
    #include <mutex>using namespace std;int fun1(int n) {int res = 1;for (int i = n; i>1; --i) {res *=i;}cout << "Result is " << res << endl;return res;
    }int main()
    {int x;//std::thread t1(fun1,4,std::ref(x));//t1.join();//我们使用异步操作,并使用get函数获取异步操作函数的合法返回值std::future<int> fu = std::async(fun1,4);x = fu.get();return 0;
    }
    

    如上代码,我们使用std::async()异步操作来创建字线程,并返回一个future类的对象,然后由future对象的get()函数来获取子线程合法的返回结果。

    关于async()等异步操作将会在下一篇进行分享,这里简单描述一下:
    async提供的是从子线程获取数值到主线程,如果我们想要从主线程获取数值到子线程,则需要promise异步操作
    查看如下代码为我们利用promise从主线程获取数值到子线程

    #include <iostream>
    #include <thread>
    #include <future>
    #include <mutex>using namespace std;int fun1(std::future<int> &f) {int res = 1;int n = f.get();for (int i = n; i>1; --i) {res *=i;}cout << "Result is " << res << endl;return res;
    }int main()
    {int x;//std::thread t1(fun1,4,std::ref(x));//t1.join();std::promise<int> p;//标示f是一个需要从未来获取数值future对象std::future<int> f = p.get_future(); std::future<int> fu = std::async(std::launch::async,fun1, std::ref(f));//为f设置数值,在子线程中进行f.get()获取主线程到数值p.set_value(4);x = fu.get();cout << "Get from child " << x << endl;return 0;
    }
    

    输出结果如下:

    Result is 24
    Get from child 24
    

    可以看到最终从子线程获取到了计算好的合法数值

  • std::future<T>::wait 阻塞线程,直到获取到可用结果

    #include <iostream>
    #include <future>
    #include <thread>int fib(int n)
    {if (n < 3) return 1;else return fib(n-1) + fib(n-2);
    }int main()
    {std::future<int> f1 = std::async(std::launch::async, [](){return fib(20);});std::future<int> f2 = std::async(std::launch::async, [](){return fib(25);});std::cout << "waiting...\n";//主线程在该处阻塞,直到获取到f1,f2两个线程到合法的结果f1.wait();f2.wait();std::cout << "f1: " << f1.get() << '\n';std::cout << "f2: " << f2.get() << '\n';
    }
    
  • wait_for()wait_until()两个函数成员同condition_variable中的类似,仍然是仅增加了需要等待的时间,到达等待的时间如仍然无法获取到合法的返回值即同样终止get

总结

可以看到我们在使用future的类的时候能够极为方便得实现线程之间的变量传递,达到更加便捷且更加安全的线程之间数据共享的目的。
关于future类的异步操作async,promise以及packaged_task的使用方式将后续分享。

C++ 多线程:future 异步访问类(线程之间安全便捷的数据共享)相关推荐

  1. linux多线程拷贝信号量运用于线程之间通讯遇到的printf问题

    linux多线程拷贝信号量运用于线程之间通讯遇到的printf问题 1.题目内容 使用多线程实现文件的拷贝,并使用进度条进行相应的显示 2.进度 以下代码实现了多线程完成文件的拷贝,但是在使用进度条实 ...

  2. WPF不同线程之间的控件的访问

    WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public void SetNotes(string n ...

  3. c++ 异步下获取线程执行结果_【分享吧】C++11多线程库介绍

    前言 对于c/c++程序员来说,编写跨平台的多线程代码十分的麻烦,因为线程的创建,同步接口在windows/linux平台上差别非常大.好在c++11标准新增了线程库,终于可以编写跨平台的多线程代码了 ...

  4. future.cancel不能关闭线程_多线程与高并发笔记

    1. 创建线程的四种方式 实现Runnable 重写run方法 继承Thread 重写run方法 线程池创建 Executors.newCachedThreadPool() 实现Callable接口 ...

  5. springboot主线程_SpringBoot(一) 多线程与异步

    多线程与异步 异步是目的,而多线程是实现这个目的的方法. 1 Java J.U.C线程调度 JDK 1.5新增的java.util.concurrent包,增加了并发编程的很多类. Executor ...

  6. Java多线程学习三十四:使用 Future 有哪些注意点?Future 产生新的线程了吗

    Future 的注意点 1. 当 for 循环批量获取 Future 的结果时容易 block,get 方法调用时应使用 timeout 限制 对于 Future 而言,第一个注意点就是,当 for ...

  7. C++多线程编程(3) 异步操作类 std::future std::promise std::async

    C++中提供了异步操作相关的类: 1. std::future: 异步结果的传输通道,可以很方便的获取线程函数的返回值. 在C++中,如果希望获取线程函数的返回值,就不能直接通过thread.join ...

  8. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  9. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

最新文章

  1. lpq命令--Linux命令应用大词典729个命令解读
  2. linux编辑文本文件aa的命令,linux入门必须掌握的命令--文本文件编辑
  3. 实例谈谈this在JavaScript中如何工作
  4. mysql aes encrypt_mysql加密函数aes_encrypt()和aes_decrypt()使用教程
  5. CEPH快速部署(Centos7+Jewel)
  6. c3p0配置及其说明
  7. centos php5.6 phpize,centos7-install-php5.6.40
  8. 如何将微商管理模式流程化
  9. 【BP回归预测】基于matlab鲸鱼算法优化BP神经网络回归预测(多输入单输出)【含Matlab源码 1554期】
  10. 树莓派实现固定IP地址
  11. 银行家算法和安全性算法笔记
  12. EasyUI 中文乱码问题
  13. hr标签html样式,hr标签样式修改及美化(css的hr标签实现精美线条)
  14. astar不能用了_解锁不可切除肝癌治疗的新时代——“T+A”北美上市会纪要
  15. 怎么判断两个多项式互素_多项式互素的等价条件
  16. 40079 钉钉_钉钉获取免登陆授权码CODE,返回:不存在的临时授权码40078
  17. 全部重点排污企业名录(整理成Excel更新至2021年)
  18. 1983—2001世嘉主机发展历程
  19. js-sha1实现SHA1加密
  20. 免费专利检索和下载网站(亲测超实用)

热门文章

  1. HTML页面加载和解析流程详细介绍
  2. request 对象和 response 对象
  3. JSP--JavaBean
  4. 一步步学习SPD2010--第十四章节--在Web页面使用控件(3)--验证用户数据输入
  5. 用C#来开发CAD插件,含源代
  6. 浏览器缓存网站静态文件
  7. 幼儿园语言活动包括哪几类_幼儿园教育:《一起玩》语言活动教案
  8. jhipster创建项目问答汇总_[恭喜JHipster社区喜提 VueJS !]
  9. python如何创建一个类_python (知识点:类)简单的创建一个类
  10. shell最大出现和连续出现次数_从 1 到 n 整数中 1 出现的次数