C++11提供的多线程开发接口中分为高级接口和低级接口;
高级接口就是C++标准库中由std::async()和class std::future<>提供的高级接口;
需求,计算两个操作数的总和,并在控制台上输出操作数表示的ASCII码;
设定两个操作数的输出字符函数分别func1和func2函数;
串行编程模型的做法是:
func1()+func2();
执行的次序为:先执行func1()函数,再执行func2()函数;总耗时为func1函数耗时+func2函数耗时+计算总和时间;或者两个函数执行顺序相反,取决于不同编译器;
并行编程模型的做法是:
对func1函数分配一个单独线程执行;
同时执行func2函数;
在计算func1和func2的和时,等待func1函数执行完成;
总耗时为:func1或者func2两者中耗时最长的时间+计算总和时间;
#include <iostream> #include <thread> #include <future> #include <chrono> #include <random> #include <exception> using namespace std; int doSomething(char c) { default_random_engine dre(c); uniform_int_distribution<int> id(10, 1000); // 在控制台上打印字符,增加延时,防止函数很快执行完成; for (size_t i = 0; i < 10; i++) { this_thread::sleep_for(chrono::milliseconds(id(dre))); cout.put(c).flush(); } return c; } int func1() { return doSomething('.'); } int func2() { return doSomething('+'); } int main() { cout << "starting func1() in background" << " and func2() in foreground:" << endl; future<int> result1(async(func1)); int result2 = func2(); int result = result1.get() + result2; cout << "\n result of func1()+func2(): " << result << endl; system("pause"); }
运行结果如下:
关于随机生成数和增加的sleep_for这部分内容不详细讲解,毕竟多线程async和future才是我们学习的目标;
与之前说过的并行编程模型的步骤相同;
函数执行的流程为:
int result = result1.get() + result2;
需要获取到func1函数的结果和func2函数的结果,func2的结果比较简单,result2就是该函数的返回值;func1由于分离到另外一个线程,就需要通过future对象来获取返回值,使用future的get函数获取func1函数的执行结果;
我们对future调用get时,会出现三种情况:
一般使用async和future怎么实现一个多线程的功能;
常规的流程是:
1.引用#include <future>; 2.传递某些可并行执行的函数,交给std::async()作为一个可调用对象(callable object)。 3.将执行结果赋值给一个future<ReturnType> object。 4.当你需要那个被启动函数的执行结果,或当你想确保该函数结束,就对future<> object调用get()。
注意:这里没有考虑到线程之间对数据的竞态情况;
注意:如果没有调用get()就不保证func1()函数会被调用;
注意:如果std::async()启动的函数是一个无返回值的函数,则会产生一个future<void>对象,是future<>的一个偏特化版,这种情况下get()返回“无物”;
注意:传给async()的东西可以是任何类型的callable object:可以是函数、成员函数、函数对象(function object)或lambda表达式;
1.《C++标准库》第二版