【C++11并发与多线程笔记(6)】

future其它成员函数、shared_future、atomic

std::future的其它成员函数

int mythread(int temp) {
	cout << temp << endl;
	cout << "mythread() start," << "threadid=" << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread() end," << "threadid=" << std::this_thread::get_id() << endl;
	return 5;
}

//main
int temp = 12;
	cout << "main," << "threadid=" << std::this_thread::get_id() << endl;
	std::future<int> result = std::async( mythread,1);
	//std::future<int> result = std::async(std::launch::deferred, mythread,1);
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	//cout << result.get() << endl;//卡在这里等待mythread()执行完毕,拿到结果。
								//get只能调用一次,不能调用多次。


std::future的其它成员函数,get()函数转移数据
//枚举类型
//std::future_status status = result.wait_for(std::chrono::seconds(1));
std::future_status status = result.wait_for(std::chrono::seconds(6));//等待一定的时间
if (status == std::future_status::timeout) {//超时,表示线程没执行完,等待线程执行一秒,希望线程返回,线程没有返回,那么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;

shared_future

int mythread(int temp) {
	cout << temp << endl;
	cout << "mythread() start," << "threadid=" << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread() end," << "threadid=" << std::this_thread::get_id() << endl;
	return 5;
}
void mythread2(std::shared_future<int>& tempfu) {//大家注意第一个参数
	int ans = tempfu.get();
	cout << "mythread2 result:" << ans << endl;
	return;
}
//main
//std::shared_future:也是类模板,get()函数复制数据
cout << "main," << "threadid=" << std::this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(mythread);
std::thread mythread(std::ref(mypt), 1);
mythread.join();
std::future<int > result = mypt.get_future();//如果有多个线程都需要mythread现成的返回结果,那么只get一次就不能完成任务了
bool canget = result.valid();
//判断future对象里面有没有有效值
//std::shared_future<int> result_s(std::move(result));
std::shared_future<int> result_s(result.share());
std::thread t2(mythread2, std::ref(result_s));
t2.join();
std::thread t3(mythread2, std::ref(result_s));
t3.join();

原子操作std::atomic

原子操作概念引出范例

原子操作概念引出范例
互斥量:多线程编程中保护共享数据,保护共享数据:锁,操作共享数据,开锁
有两个线程,这两个线程对一个变量进行操作,这个线程读,另一个线程往这个变量里面写值
大家可以把原子操作理解为一种:不需要用到互斥量加锁(无锁)技术的多线程并发编程方式
在多线程中,不会被打断的程序执行片段;原子操作,比互斥量效率上更胜一筹
互斥量的加锁一般是针对一个代码段(几行代码),而原子操作针对的一般都是一个变量,而不是一个代码段;
原子操作:不可分割的操作,也就是这种操作要么是完成的,要么就是都没完成的, 不可能出现半完成状态;
std::atomic来代表原子操作,std::atomic是个类模板,std::atomic

int g_mycout = 0;
std::atomic<int> g_mycout = 0;//我们封装了一个类型为int的对象,我们可以像操作一个int类型变量一样来操作这个g_mycout
void mythread() {
	for (int i = 0; i < 10000000; i++) {
		g_mycout++;//对应的操作是原子操作(不会被打断)
	}
}
//main
std::thread myth1(mythread);
std::thread myth2(mythread);
myth1.join();
myth2.join();
cout << "两个线程执行完了,最终的g_mycount的结果是:" << g_mycout << endl;

基本的std::atomic用法范例

std::atomic<bool> g_ifend = false;
void mythread() {
	std::chrono::milliseconds dura(1000);
	while (g_ifend == false) {
		//系统没要求线程退出,所以本线程可以自己干自己相干的事情
		cout << "thread id=" << std::this_thread::get_id() << "运行中。。。。" << endl;
		std::this_thread::sleep_for(dura);
	}
}
//main
std::thread myth1(mythread);
std::thread myth2(mythread);
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
g_ifend = true;
myth1.join();
myth2.join();

心得

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

原子操作std::atomic续谈

std::atomic<int> g_mycout = 0;//我们封装了一个类型为int的对象,我们可以像操作一个int类型变量一样来操作这个g_mycout
void mythread() {
	for (int i = 0; i < 10000000; i++) {
		//g_mycout++;//对应的操作是原子操作(不会被打断)
		//g_mycout += 1;
		g_mycout = g_mycout + 1;
	}
}
//main
cout << "main," << "threadid=" << std::this_thread::get_id() << endl;
cout << "continue................!!" << endl;
cout << "continue................!!" << endl;
cout << "continue................!!" << endl;
cout << "continue................!!" << endl;
cout << "continue................!!" << endl;
cout << "continue................!!" << endl;
std::thread myth1(mythread);
std::thread myth2(mythread);
myth1.join();
myth2.join();
cout << "两个线程执行完了,最终的g_mycount的结果是:" << g_mycout << endl;

原子操作std::atomic续谈
一般atomic原子操作,针对++,–,+=,&=,|=,=是支持的,其他的可能不支持

std::async深入谈

std::async参数详述

std::async参数详谈,async用来创建一个异步任务
讲解过:参数std::launch::deferred【延迟调用】,以及std::launch::async【强制创建一个线程】
std::thread()如果系统资源紧张,那么可能创建线程可能就会失败,那么执行std::thread()时整个程序可能崩溃。
std::async()一般不叫作创建线程(但是async能够创建线程),我们一般叫它创建 一个异步任务。
std::async和std::thread最明显的不同,就是async有时候并不创建新线程。
a)如果你用std::launch::deferred来调用async会怎么样?
deferred延迟调用,并且不创建新线程,延迟到future对象调用get()或者wait的时候,才执行mythread(),如果没有调用get或者wait,则不进行异步操作
b)std::launch::async强制异步任务在新线程上执行,这意味着,系统必须要给我创建出新线程来运行mythread();
c)std::launch::deferred|std::launch::async
这个 | :意味着调用async的行为可能是“创建新线程并立即执行”或者
“没有创建新线程并且延迟到调用result.get()才开始执行任务入口函数”,两者居其一
d)我们不带额外参数,只给async函数一个一个入口函数名;
其实,默认值应该是std::launch::deferred|std::launch::async和c)效果完全一致,系统会自动决定是同步还是异步进行。
自行决定是啥意思?系统是如何决定是异步(创建新线程)还是同步(不创建新线程)方式运行

std::async和std::thread的区别

std::thread创建线程,如果,系统资源紧张,创建资源失败,整个程序就会报异常崩溃,
int mythread(){return 1;}
std::thread myobj(mythread);
myobj.join();
std::thread创建线程的方式,如果线程返回值,你想拿到这个值也不容易
std::async创建异步任务,可能创建也可能不创建线程,并且async调用方法很容易
由于系统资源限制:
(1)如果用std::thread创建的线程太多,则可能创建失败,系统报告异常,崩溃。
(2)如果用std::async,一般就不会报告异常不会崩溃,因为如果系统资源紧张导致无法创建新线程的时候,
std::async不加额外参数的调用就不会创建新线程,而是后续谁调用了result.get()来请求结果
那么这个异步任务就会运行在这条get()语句所在的线程上。
如果你强制std::async一定要创建新线程,那么就必须执行std::launch::async承受的代价就是系统资源紧张时,程序崩溃。
经验:一个程序里面,线程的数量不宜超过100-200.

std::async不确定性问题的解决

std::async不确定性
不加额外参数的std::async调用,让系统自行决定是否创建新线程。
问题焦点在于 std::future result=std::async(mythread)
这个异步任务到底有没有被推迟执行,(std::launch::async还是std::launch::deferred)
std::future 对象的wait_for()函数

int mythread() {
	cout << "mythread()开始了!" << endl;
	cout << "mythread()id="<<std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread()结束了了!" << endl;
	return 1;
}
//main
	cout << "main," << "threadid=" << std::this_thread::get_id() << endl;
	//std::future<int> result = std::async(std::launch::deferred, mythread,1);
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	cout << "continue................!!" << endl;
	future<int> result= std::async(mythread);//想判断async到底有没有创建新线程,立即执行还是延迟执行
	std::future_status status = result.wait_for(std::chrono::seconds(0));//等待一定的时间
	 if (status == std::future_status::deferred) {
		 //线程被延迟执行了(系统资源紧张了,它给我采用std::launch::deferred策略了)
		cout << "线程延迟执行!" << endl;
		cout << result.get() << endl;
	 }
	 else {
		 //任务没被推迟,已经开始运行了,线程被创建了
		 if (status == std::future_status::timeout) {

			 cout << "超时,线程还没走执行完!" << endl;
			 cout << result.get() << endl;
		 }
		 else if (status == std::future_status::ready) {
			 cout << "线程成功返回!" << endl;
			 cout << result.get() << endl;
		 }
	 }
	cout << "I love china!" << endl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值