C++11 线程共享状态

C++11 线程共享状态


一、问题提出

首先,我们假设一种情况,在多线程中,出现这么一种情况:
两条线程:thread1 和 thread2
某种特殊环境中,thread2需要得到thread1中的某个值才能进行数据处理,那怎么做才能达到这种效果?
方法一:
在主线程中等待,直到thread1处理完后,按顺序处理thread2;
但是这种效率太低,导致主线程一直阻塞等待

方法二:
同时开启两个线程,thread1和thread2;在thread2中阻塞等待thread1处理好数据,并进行下一步操作
优点:
不需要更多的资源来等待thread1的完成

那具体怎么做呢?
还好C++11 为我们提供了相关的函数类:promise和future


二、promise和future

头文件:

#include <future>

promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保存一个类型为 T 的值。

可以通过 get_future 来获取与该 promise 对象相关联的 future 对象,调用该函数之后,两个对象共享相同的共享状态(shared state)

  • promise 对象是异步 Provider,它可以在某一时刻设置共享状态的值。
  • future 对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为 ready,然后才能获取共享状态的值。

主要涉及到这几个函数:

std::promise::get_future:返回一个与promise共享状态相关联的future对象 
std::promise::set_value:设置共享状态的值,此后promise共享状态标识变为ready 
std::promise::set_exception:为promise设置异常,此后promise的共享状态标识变为ready 
std::promise::set_value_at_thread_exit:设置共享状态的值,但是不将共享状态的标志设置为 ready,当线程退出时该 promise 对象会自动设置为 ready(注意:该线程已设置promise的值,如果在线程结束之后有其他修改共享状态值的操作,会抛出future_error(promise_already_satisfied)异常) 
std::promise::swap:交换 promise 的共享状态

std::future
简单来说,std::future提供了一种访问异步操作结果的机制。

通常一个异步操作我们是不能马上就获取操作结果的,只能在未来某个时候获取。我们可以以同步等待的方式来获取结果,可以通过查询future的状态(future_status)来获取异步操作的结果。future_status有三种状态:
deferred:异步操作还没开始
ready:异步操作已经完成
timeout:异步操作超时

获取future结果有三种方式:get、wait、wait_for,其中get等待异步操作结束并返回结果,wait只是等待异步操作完成,没有返回值,wait_for是超时等待返回结果。


注意:一个promise只能被获取到一次。


三、案例
#include <iostream>
#include <future>
#include <thread>
#include <exception>

using namespace std;

typedef struct PF 
{
	string name;
	int age;
};


void get_int(promise<PF>&prom)
{
	try 
	{
		PF pf;
		memset(&pf, 0, sizeof(pf));
		pf.name = "test";
		pf.age = 10;
		//设置共享状态
		prom.set_value(pf);
	}
	catch(exception)
	{
		prom.set_exception(current_exception());
	}
}

void print_int(future<PF>&fut)
{
	try
	{
		PF pf;
		memset(&pf, 0, sizeof(pf));
		获取共享状态
		pf = fut.get();
		cout << "age:"<<pf.age << endl;
		cout << "name:" << pf.name.c_str() << endl;
	}
	catch (exception& e)
	{
		cout << "exception:"<<e.what() << endl;
	}

}

int main()
{
	PF pf;
	memset(&pf,0,sizeof(pf));
	//生成对象
	promise<PF>prom;
	//与future关联
	future<PF>fut = prom.get_future();
	thread *t1 = new thread(get_int,ref(prom));
	thread *t2 = new thread(print_int,ref(fut));
	t1->join();
	t2->join();
	delete t1;
	delete t2;
	return 0;
}

想了解学习更多C++后台服务器方面的知识,请关注:
微信公众号:C++后台服务器开发


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值