C++线程与Future、Promise模板

多线程编程中,需要数据共享,如一个线程需要使用另一线程运算产生的数据。

涉及到异步编程时,有时需要线程间同步,如执行异步订阅消息时,当订阅消息的结果返回成功后,处理消息的线程才需要运行。

以上场景的都可以使用std::future和std::promise实现

例子1

#include<iostream>
#include<future>
#include<mutex>
#include<chrono>
#include<thread>
#include<stdlib.h>
using namespace std;
void Thread_Fun1(std::promise<int> &p)
{
	//为了突出效果,可以使线程休眠5s
	// std::this_thread::sleep_for(std::chrono::seconds(5));
 
	int iVal = 233;
	std::cout << "传入数据(int):" << iVal << std::endl;
 
	//传入数据iVal
	p.set_value(iVal);
} 
void Thread_Fun2(std::future<int> &f)
{
	//阻塞函数,直到收到相关联的std::promise对象传入的数据
	auto iVal = f.get();		//iVal = 233
 
	std::cout << "收到数据(int):" << iVal << std::endl;
}
 
int main()
{
	//声明一个std::promise对象pr1,其保存的值类型为int
	std::promise<int> pr1;
	//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
	std::future<int> fu1 = pr1.get_future();
 
	//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行  //std::ref,表示我们想要传递的是变量本身
	std::thread t1(Thread_Fun1, std::ref(pr1));
	//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
	std::thread t2(Thread_Fun2, std::ref(fu1));
 
	//阻塞至线程结束
	t1.join();
	t2.join();

	system("pause");
 
	return 0;
}

执行结果:

传入数据(int):233
收到数据(int):233

多线程共享值

步骤:

  1. 在一个线程A中创建一个 std::promise 对象:std::promise<int> proObj;
  2. 把 std::promise 关联到 std::future: std::future<int> futObj = proObj.get_future();
  3. 把 proObj 对象传递给另一个线程B,线程B会在适当的时刻设置该对象的值:proObj.set_value(23);
  4. 在线程A中通过 std::future 读取对象的值:int val = futObj.get();

就是这么简单,不管线程B在何时设置对象的值,线程A总能安全地获取。有一个点需要注意,在A中通过futObj.get()获取值时,若B还未设置,则A会阻塞,直到设置了值并成功获取。
在这里插入图片描述

例子2

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
 
// 线程B
void initiazer(std::promise<int> * promObj)
{
    std::cout << "Thread B" << std::endl;
    // set the value at proper time
    std::this_thread::sleep_for(std::chrono::seconds(3));
    promObj->set_value(23);
}
 
int main()
{
		// 线程A
    std::promise<int> promiseObj;
    std::future<int> futureObj = promiseObj.get_future();
    
    std::thread th(initiazer, &promiseObj); // 启动线程B
	// std::thread th(initiazer, std::ref(promiseObj)); // 启动线程B 对应上面函数参数就得用&引用
    
    // 获取对象的值,该调用在B设置其值后会返回23,在B设置其值前会阻塞
    std::cout<< futureObj.get() << std::endl;
    
    th.join();
    
    return 0;
}

 执行结果:

Thread B
23

线程间同步

可以使用如下代码判断共享对象的值是否就绪:

template<typename T>
bool is_ready(std::future<T> const& f)
{ return f.wait_for(std::chrono::seconds(3)) == std::future_status::ready; }

future对象的wait_for函数会阻塞等待结果变得可用,可用的标志为以下两种情况之一:

  • 设置的时间超时
  • 共享对象的状态变为ready

它的原型如下:

template< class Rep, class Period >
std::future_status wait_for( const std::chrono::duration<Rep,Period>& timeout_duration ) const;

返回值标识了结果的状态,为:

  • future_status::deferred :计算结果的函数未启动
  • future_status::ready:结果ready
  • future_status::timeout:超时

例子3

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
 
// 线程B
void loginSrv(std::promise<bool> * promObj)
{
    std::cout << "Thread B" << std::endl;
    // set the value
    std::this_thread::sleep_for(std::chrono::seconds(3));
    // if (loginSucc)
    // 		promObj->set_value(true);
    // else
    		promObj->set_value(false);
}
 
int main()
{
		// 线程A
    std::promise<bool> promiseObj;
    std::future<bool> futureObj = promiseObj.get_future();
    
    std::thread th(loginSrv, &promiseObj); // 启动线程B
    
    // 阻塞8s等待登录结果,若8s内未返回结果,则超时
    if (futureObj.wait_for(std::chrono::seconds(8)) == std::future_status::ready)
       	if (futureObj.get()) // 返回登录结果,不会再阻塞
       			std::cout<<"doLoginSuccThings"<< std::endl;
       	else
       			std::cout<<"doLoginFailedThings"<< std::endl;
    else
        // 超时未登录成功
        std::cout<<"doOtherThings"<< std::endl;
    
    th.join();
    system("pause");
    return 0;
}

执行结果:

Thread B
doLoginFailedThings

小结:

  1. 使用promise和future能够快速地进行线程间数据共享和同步。
  2. promise提供值,并在以后改变值(set_value)。
  3. future关联到promise,线程安全地获取值(get)。
  4. 利用future的阻塞等待特性(wait_for),可以实现线程同步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值