6-10 future其他成员函数、shared_future、ato

一:std::future的其他成员函数

int mythread()
{
	cout<<"mythread() start"<<"threadid="<<std::this_thread::get_id()<<endl;//新的线程id
	std::chrono::milliseconds dura(5000);//1秒=1000毫秒,所以5000毫秒=5秒
	std::this_thread::sleep_for(dura);	//休息一定的时长
	cout<<"mythread() end"<<"threadid ="<<std::this_thread::get_id()<<endl;
	return 5;
}
int main()
{
	cout<<"main"<<"threadid="<<std::this_thread::get_id()<<endl;
	std::future<int> result = std::async(std::launch::deferred,mythread);	//流程并不会卡在这里
	cout<<"continue....!"<<endl;
	//cout<<result.get()<<endl;	//卡在这里等待线程执行完,
							//但是这种get因为一些内部特殊操作,不能get多次,只能get一次
	//枚举类型:
	std::future_status status = result.wait_for(std::chrono::seconds(1));//等待1秒
	if(status == std::future_status::timeout)//超时,我想等待你1秒钟,希望你返回,你没返回,那么status = timeout
	{
		//表示线程还没执行完;
		cout<<"超时,线程还没有执行完毕"<<endl;
	}
	else if(status == std::future_status::ready)
	{
		//表示线程成功返回
		cout<<"线程成功执行完毕,返回"<<endl;
		cout<<result.get()<<endl;
	}
	else if(status == std::future_status::deferred)//延迟
	{
		//如果async的第一个参数被设置为std::launch::deferred,则本条件成立
		cout<<"线程被延迟执行"<<endl;
		cout<<result.get()<<endl;
	}
	cout<<"I Love China!"<<endl;
	return 0;
}

二:std::shared_future

也是个类模板,get()函数复制数据

int mythread(int mypar)
{
	cout<<"mythread() start"<<"threadid ="<<std::this_thread::get_id()<<endl;
	std::chrono::milliseconds dura(5000);//1秒=1000毫秒,所以5000毫秒=5秒
	std::this_thread::sleep_for(dura);//休息一定的时长
	return 5;
}
void mythread2(std::future<int> &tmpf)//注意参数
{
	cout<<"mythread2() start"<<"threadid="<<std::this_thread::get_id()<<endl;
	auto result = tmpf.get();//获取值,只能get一次否则会报异常
				//为什么第二次get这个future我们会得到一个异常;主要是因为get函数的设计是一个移动语义
	cout<<"mythread2 result="<<result<<endl;
	return;
}
int main()
{
	cout<<"main"<<"threadid="<<std::this_thread::get_id()<<endl;
	std::packaged_task<int(int)> mypt(mythread);//我们把函数mythread通过packaged_task包装起来;
	std::thread t1(std::ref(mypt),1);	//线程直接开始执行,第二个参数作为线程入口函数的参数;
	t1.join();//我们可以调用这个等待线程执行完毕,不调用这个不太行,会崩溃
	//std::future<int>result = mypt.get_future();//std::future大家不陌生了,这个对象里含有线程入口函数

	//bool ifcanget = result.valid();
	//std::shared_future<int> result_s(result.share());//执行完毕后result_s里有值,而result里空了
	//ifcanget = result.valid();
	std::shared_future<int> result_s(mypt.get_future());//通过get_future返回值直接构造了一个shared_future对象。
	auto mythreadresult = result_s.get();
	mythreadresult = result_s.get();

	std::thread t2(mythread2,std::ref(result));
	t2.join();	//等线程执行完毕
	cout<<"I Love China!"<<endl;
	return 0;
}

三:原子操作std::atomic

3.1、原子操作概念引出范例
互斥量:多线程编程中保护共享数据:锁,操作共享数据,开锁
有两个线程,对一个变量进行操作,这个线程读该变量值,另一个线程往这个变量中写值。
int atomvalue = 5;
//读线程
int tmpvalue = atomvalue; //这里这个atomvalue代表的是多个线程之间要共享的变量;
//写线程B
atomvalue = 6; //汇编代码的话;
大家可以把原子操作理解成一种:不需要用到互斥量加锁(无锁)技术的多线程并发编程方式
原子操作:是在多线程中不会被打断的程序执行片段;原子操作,比互斥量效率上更胜一筹。
互斥量的加锁一般是针对一个代码段(几行代码),而原子操作针对的一般都是一个变量,而不是一个代码段;
原子操作,一般都是指“不可分割的操作”;也就是说这种操作状态要么是完成的,要么是没完成的,不可能出现半完成状态;
std::atomic来代表原子操作,std::atomic是个类模板。其实std::atomic这个东西是用来封装某个类型的值的;

3.2、一般用于计数或者统计(累计发送出去了多少个数据包,累计接收到了多少个数据包;)

//int g_mycout = 0;//定义一个全局量
//std::mutex g_my_mutex;	//互斥量
std::atomic<int> g_mycout = 0;//我们封装了一个类型为int的对象(值);我们可以像操作一个int类型变量一样来操作这个g_mycout

void mythread()	//线程入口函数
{
	for(int i = 0;i<100000;i++)
	{
		//g_my_mutex.lock();
		g_mycout++;
		//g_my_mutex.unlock();
	}
	return;
}
void main()
{
	thread mytobj1(mythread);
	thread mytobj2(mythread);
	mytobj1.join();
	mytobj2.join();
	cout<<"两个线程执行完毕,最终的g_mycount的结果是:"<<g_mycout<<endl;

}

猜你喜欢

转载自blog.csdn.net/qq_39885372/article/details/107116832
今日推荐