首先查看如下代码
#include
#include
#include
#include 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
类对以上操作进行简化。
template< class T > class future;
future
类模版提供了一种异步访问操作机制如下: std::async
、 std::packaged_task
或 std::promise
的返回值为std::future
对象std::async
创建的异步操作返回的future
对象未获取值,那么std::async
将不会退出std::future
的共享状态(例如std::promise::set_value
)进行std::future
获取异步操作的返回结果
get 方法等待直至 future 拥有合法结果并(依赖于使用哪个模板)获取它。它等效地调用 wait() 等待结果
这里需要简单说明下get函数的返回值,它的返回值为std::move()
类型,即将之前的返回结果包括值和地址都进行赋值。如果二次尝试get
,回访问到空的值和地址,报出异常std::future_error
。
我们对刚开始的代码更改如下:
#include
#include
#include
#include 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
#include
#include
#include 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
阻塞线程,直到获取到可用结果
#include
#include
#include 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...
";//主线程在该处阻塞,直到获取到f1,f2两个线程到合法的结果f1.wait();f2.wait();std::cout << "f1: " << f1.get() << '
';std::cout << "f2: " << f2.get() << '
';
}
wait_for()
和wait_until()
两个函数成员同condition_variable
中的类似,仍然是仅增加了需要等待的时间,到达等待的时间如仍然无法获取到合法的返回值即同样终止get
可以看到我们在使用future的类的时候能够极为方便得实现线程之间的变量传递,达到更加便捷且更加安全的线程之间数据共享的目的。
关于future
类的异步操作async
,promise
以及packaged_task
的使用方式将后续分享。
经过长期探索,发现一个不需要手动设置线程休眠时间(e.g. std::this_thread::sleep_for(std::chrono::microseconds(1)))的代码: Github: https://github.com/log4cplus/ThreadPool #ifndef THREAD_POOL_H_7e...
nth_element(first,nth,last) first,last 第一个和最后一个迭代器,也可以直接用数组的位置。 nth,要定位的第nn 个元素,能对它进行随机访问. 将第n_thn_th 元素放到它该放的位置上,左边元素都小于它,右边元素都大于它. 测试代码: http://www.cplusplus.com...
c/c++老版本的rand()存在一定的问题,在转换rand随机数的范围,类型或者分布时,常常会引入非随机性。
定义在
jsoncpp 是一个C++ 语言实现的json库,非常方便得支持C++得各种数据类型到json 以及 json到各种数据类型的转化。 一个json 类型的数据如下: {"code" : 10.01,"files" : "","msg" : "","uploadid" : "UP000000" } 这种数据类型方便我们人阅读以...
问题如下: 已知一组数(其中有重复元素),求这组数可以组成的所有子集中,子 集中的各个元素和为整数target的子集,结果中无重复的子集。 例如: nums[] = [10, 1, 2, 7, 6, 1, 5], target = 8 结果为: [[1, 7], [1, 2, 5], [2, 6], [1, 1, 6]] 同样之前有...
Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。 我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...
利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...
题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...
题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树: 5 / 2 6 / 1 3示例 1: 输入: [1,6,3,2,5] 输出...