c++11并发编程三(使用std::future、std::promise获取线程返回值)

在前两篇对std::thread的使用中有一个问题:线程的执行函数都是没有返回值的。而且就算有返回值,在C++11 thread中也会忽略掉,那么,如果我们需要获取函数的返回值,应该怎么办?

1.传统的方法:在线程间共享指针

主线程传递一个指针给工作线程,指针指向的是需要返回的值的地址空间,工作线程把返回值写入该地址,然后唤醒主线程,主线程再去取该返回值。这样做的不便之处在于:主线程和工作线程共享了该地址空间,对共享变量的修改需要加互斥锁和条件变量,如果返回值有多个,这个过程会更加复杂。

2.c++11的方法:使用std::future和std::promise

  • std::future是一个类模板(class template),其对象存储未来的值,
  • 到底什么是未来的值呢?事实上,一个std::future对象在内部存储一个将来会被赋值的值,并提供了一个访问该值的机制,通过get()成员函数实现。但如果有人视图在get()函数可用之前通过它来访问相关的值,那么get()函数将会阻塞,直到该值可用。
  • std::promise也是一个类模板,其对象有可能在将来会被人为赋值每个std::promise对象有一个对应的std::future对象,一旦由std::promise对象设置,std::future将会对其赋值。
  • std::promise对象与其管理的std::future对象共享数据。

std::promise and std::future

step1:在线程1中创建一个std::promise对象

std::promise<int> promiseObj;

目前为止,该promise对象没有任何管理的值,但它承诺肯定会有人对其进行赋值,一旦被赋值,就可以通过其管理的std::future对象来获取该值。假设线程1创建了该promise对象并将其传给线程2,那么线程1怎样知道线程2什么时候会对promise对象进行赋值呢?
答案是使用std::future对象

每个std::promise对象都有个对应的std::future对象,其他人可以通过它来获取promise设置的值。所以,线程1将会创建std::promise对象,然后在将其传递给线程2之前从它那里获取std::future对象

step2:从std::promise中获取std::future对象

std::future<int> futureObj = promiseObj.get_future();

现在,线程1将promiseObj传递给线程2,那么线程1将会获取到线程2通过std::future的get函数设置在std::promise中的值。

但是如果线程2还没有对该值进行设置,那么这个调用将会阻塞,直到线程2在promise对象中对该值进行设置。

step3:线程1将promiseObj传给线程2,阻塞等待线程2对promise对象中的future赋值

看一个完整的std::future和std::promise的例子:

#include <iostream>
#include <thread>
#include <future>
 
void initiazer(std::promise<int>* promObj){
	std::cout<<"Inside Thread"<<std::endl;
	promObj->set_value(35);
}
 
int main(){
	std::promise<int> promiseObj;
	std::future<int> futureObj = promiseObj.get_future();
	std::thread th(initiazer, &promiseObj);
	std::cout<<futureObj.get()<<std::endl;
	th.join();
 
	return 0;
}

  • 如果std::promise对象在赋值之前被销毁,那么管理的std::future对象上的get()调用将会抛出异常。
  • 除此之外,如果想要线程在不同时间点返回多个值,只需要在线程中传输多个std::promise对象,并从相关的多个std::futur对象中获取多个返回值。

猜你喜欢

转载自blog.csdn.net/weixin_44843859/article/details/112187118
今日推荐