C++ 多线程:future 异步访问类(线程之间安全便捷的数据共享)
文章目录
- 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::async
、std::packaged_task
或std::promise
的返回值为std::future
对象 - 异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。如使用
std::async
创建的异步操作返回的future
对象未获取值,那么std::async
将不会退出 - 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的
std::future
的共享状态(例如std::promise::set_value
)进行
- 异步操作能提供一个 std::future 对象给该异步操作的创建者。其中包括
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 异步访问类(线程之间安全便捷的数据共享)相关推荐
- linux多线程拷贝信号量运用于线程之间通讯遇到的printf问题
linux多线程拷贝信号量运用于线程之间通讯遇到的printf问题 1.题目内容 使用多线程实现文件的拷贝,并使用进度条进行相应的显示 2.进度 以下代码实现了多线程完成文件的拷贝,但是在使用进度条实 ...
- WPF不同线程之间的控件的访问
WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public void SetNotes(string n ...
- c++ 异步下获取线程执行结果_【分享吧】C++11多线程库介绍
前言 对于c/c++程序员来说,编写跨平台的多线程代码十分的麻烦,因为线程的创建,同步接口在windows/linux平台上差别非常大.好在c++11标准新增了线程库,终于可以编写跨平台的多线程代码了 ...
- future.cancel不能关闭线程_多线程与高并发笔记
1. 创建线程的四种方式 实现Runnable 重写run方法 继承Thread 重写run方法 线程池创建 Executors.newCachedThreadPool() 实现Callable接口 ...
- springboot主线程_SpringBoot(一) 多线程与异步
多线程与异步 异步是目的,而多线程是实现这个目的的方法. 1 Java J.U.C线程调度 JDK 1.5新增的java.util.concurrent包,增加了并发编程的很多类. Executor ...
- Java多线程学习三十四:使用 Future 有哪些注意点?Future 产生新的线程了吗
Future 的注意点 1. 当 for 循环批量获取 Future 的结果时容易 block,get 方法调用时应使用 timeout 限制 对于 Future 而言,第一个注意点就是,当 for ...
- C++多线程编程(3) 异步操作类 std::future std::promise std::async
C++中提供了异步操作相关的类: 1. std::future: 异步结果的传输通道,可以很方便的获取线程函数的返回值. 在C++中,如果希望获取线程函数的返回值,就不能直接通过thread.join ...
- VC中利用多线程技术实现线程之间的通信
当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...
- 详解Java多线程编程中LockSupport类的线程阻塞用法
转载自 详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...
最新文章
- lpq命令--Linux命令应用大词典729个命令解读
- linux编辑文本文件aa的命令,linux入门必须掌握的命令--文本文件编辑
- 实例谈谈this在JavaScript中如何工作
- mysql aes encrypt_mysql加密函数aes_encrypt()和aes_decrypt()使用教程
- CEPH快速部署(Centos7+Jewel)
- c3p0配置及其说明
- centos php5.6 phpize,centos7-install-php5.6.40
- 如何将微商管理模式流程化
- 【BP回归预测】基于matlab鲸鱼算法优化BP神经网络回归预测(多输入单输出)【含Matlab源码 1554期】
- 树莓派实现固定IP地址
- 银行家算法和安全性算法笔记
- EasyUI 中文乱码问题
- hr标签html样式,hr标签样式修改及美化(css的hr标签实现精美线条)
- astar不能用了_解锁不可切除肝癌治疗的新时代——“T+A”北美上市会纪要
- 怎么判断两个多项式互素_多项式互素的等价条件
- 40079 钉钉_钉钉获取免登陆授权码CODE,返回:不存在的临时授权码40078
- 全部重点排污企业名录(整理成Excel更新至2021年)
- 1983—2001世嘉主机发展历程
- js-sha1实现SHA1加密
- 免费专利检索和下载网站(亲测超实用)
热门文章
- HTML页面加载和解析流程详细介绍
- request 对象和 response 对象
- JSP--JavaBean
- 一步步学习SPD2010--第十四章节--在Web页面使用控件(3)--验证用户数据输入
- 用C#来开发CAD插件,含源代
- 浏览器缓存网站静态文件
- 幼儿园语言活动包括哪几类_幼儿园教育:《一起玩》语言活动教案
- jhipster创建项目问答汇总_[恭喜JHipster社区喜提 VueJS !]
- python如何创建一个类_python (知识点:类)简单的创建一个类
- shell最大出现和连续出现次数_从 1 到 n 整数中 1 出现的次数