第七章 Future,Promise and async()——线程通信

版权声明:本文为博主原创文章,转载时请注明来源。有问题请e-mail:[email protected] https://blog.csdn.net/u011177305/article/details/52227848

本章目标:

主线程与次线程通信的问题

次线程与主线程通信的问题

  

案例清单:计算阶乘代码示例

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

#include<fstream>

  

using namespace std;

  

void factorial(int N)

{

int res = 1;

for (int i = N; i > 1; i--)

{

res *= i;

}

cout << "results" << res << endl;

}

  

int main()

{

std::thread t1(factorial,4);

  

t1.join();

return 0;

}

  

但是,如果将子线程打印的结果res返回到主线程main中,根据前面的知识,则可能需要使用下面的方法

  

//……

  

void factorial(int N,int &x)

{

  

int res = 1;

for (int i = N; i > 1; i--)

{

res *= i;

}

cout << "results" << res << endl;

x = res;

}

  

int main()

{

int x;

std::thread t1(factorial,4,std::ref(x));

  

t1.join();

return 0;

}

  

但这样还不够,这是因为x被主线程和次线程同时共享,因此需要设置互斥,添加锁。由于x的传递,因此还要使用条件变量std::condition_variable cond;显然程序中还要加入wait(),unlock()从而使得程序变得复杂。

  

解决方式为使用std::future<>模板库。

代码清单:

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

#include<fstream>

  

using namespace std;

  

int factorial(int N)

{

  

int res = 1;

for (int i = N; i > 1; i--)

{

res *= i;

}

cout << "results" << res << endl;

return res;

}

#include<future>

int main()

{

int x;

std::future<int>fu = std::async(factorial,4);

//std::thread t1(factorial,4,std::ref(x));

x = fu.get();

//t1.join();

return 0;

}

  

结果如下

  

果,因为 std::thread 并不提供直接接收返回值的机制。这里就需要 std::async 函数模板(也 是在头文件中声明的)了。

当任务的结果你不着急要时,你可以使用 std::async 启动一个异步任务。与 std::thread 对 象等待运行方式的不同, std::async 会返回一个 std::future 对象,这个对象持有最终计算 出来的结果。当你需要这个值时,你只需要调用这个对象的get()成员函数;并且直到"期望"状 态为就绪的情况下,线程才会阻塞;之后,返回计算结果。下面清单中代码就是一个简单的

例子。

  

  

关注如何传回计算的结果,因为 std::thread 并不提供直接接收返回值的机制。这里就需要 std::async 函数模板(也

是在头文件中声明的)了。

  

当任务的结果你不着急要时,你可以使用 std::async 启动一个异步任务。与 std::thread 对象等待运行方式的不同, std::async 会返回一个 std::future 对象,这个对象持有最终计算出来的结果。当你需要这个值时,你只需要调用这个对象的get()成员函数;并且直到"期望"状态为就绪的情况下,线程才会阻塞;之后,返回计算结果。

  

Std::async并不一定会创建一个新的线程,如果添加参数 std::launch::deferred后,即std::future<int > fu=std::async(std::launch::deferred,factorial,4);则不会启动新的线程,到了x=fu.get()时,会在原来的线程中调用factorial函数。而使用std::launch::async后则表示创建新的线程。由于这两种为"或"的关系,因此,可以像清单中的表示。

  

从子线程获取主线程中的变量

  

上面的是从主线程获得子线程中的变量,下面是从子线程获得主线程变量的方法。

  

使用promise类型的变量。代码清单如下:

  

#include<iostream>

#include<string>

#include<thread>

#include<mutex>

#include<fstream>

  

using namespace std;

  

int factorial(std::future<int>& f)

{

  

int res = 1;

int N = f.get();

for (int i = N; i > 1; i--)

{

res *= i;

}

cout << "results" << res << endl;

return res;

}

#include<future>

int main()

{

int x;

std::promise<int> p;

std::future<int> f = p.get_future();

  

std::future<int>fu = std::async(factorial,std::ref(f));

//std::thread t1(factorial,4,std::ref(x));

  

p.set_value(4);//如果使用了promise而没有set_value,此时子线程

//f.get()将抛出一个std::future_error::broken_promise

//的异常

 

  

x = fu.get();

cout << "get from child thread:" << x << endl;

//t1.join();

return 0;

}

  

  

执行结果,可以看出子线程的结果为24,主线程也显示出对应的子线程中的结果。

  

  

注意:promisefuture不可以使用copy,但是可以使用move

Std::promise<int> p2=p; //这是错误的

但是

Std::promise<int >p2=std::move(p);//这是正常的,可是使用的。

  

假如主线程中的factorial需要执行多次,能否可以创建对于很多线程的同步问题,可以创建多个

可以使用share_future

  

 

  

•假设,你有一个需要长时间的运算,你需要其能计算出一个有效的值,但是你现在并不迫切 需要这个值。你可以启动一个新线程来执行这个计算,但是这就意味着你必须关注如何传回计算的结

_

猜你喜欢

转载自blog.csdn.net/u011177305/article/details/52227848