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

12 篇文章 0 订阅
10 篇文章 0 订阅

本章目标:

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

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

  

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

#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

  

 

  

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

_

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值