7.condition_variable,wait,notify_one,notify_all

condition_variable, wait, notify_one

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
using namespace std;

class A {
public:
	void inMsg() {
		for (int i = 0; i < 10000; i++) {		
			cout << "插入一个元素:" << i << endl;
			std::unique_lock<mutex>myguard(myMutex);
			myQueue.push(i);
			//假设outMsg正在处理一个事务,需要一段时间,而不是正卡在wait那里等你唤醒,那么这个notify_one就没意义
			my_cond.notify_one();//我们尝试把wait()的线程唤醒,执行完这行,那么outMsg()里边的wait就会被唤醒,唤醒之后的事情后续研究
		}
	}
	void outMsg() {
		int command;
		while (1) {
			std::unique_lock<std::mutex>myguard(myMutex);
			//wait用来等待一个东西
			//如果第二个参数lambda表达式返回值是true,那么wait()直接返回
			//如果第二个参数lambda表达式返回值是false,那么wait()将解锁unlock互斥量,并堵塞到本行
			//那堵塞到什么时候为止呢?堵塞到其他某个线程调用notify_one()成员函数为止
			//如果wait()没有第二个参数:my_cond.wait(myguard),那么就跟第二个参数lambda表达式返回false效果一样
			
			//当其他线程用notify_one()将本wait(原本是睡着/堵塞)的状态唤醒后,wait就开始恢复干活了,恢复后wait干什么活?
				//a)wait()不断地尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等待获取,如果获取到了锁(等于加了锁),那么wait就继续执行 b)
				//b)
					//b.1)如果wait有第二个参数(lambda)就判断这个lambda表达式,如果lambda表达式为false,那wait又对互斥量解锁,继续休眠在这里等待再次被notify_one唤醒
					//b.2)如果lambda表达式为true,则wait返回,流程走下来(此时互斥量锁被锁着)
					//b.3)如果wait没有第二个参数,则wait返回,流程走下来

			my_cond.wait(myguard, [this] {
				if (!this->myQueue.empty())
					return true;
				return false;
			});

			// ....
			// ....
			//流程只要能走到这里来,这个互斥锁一定是锁着的,同时myQueue肯定不为空

			command = myQueue.front();
			myQueue.pop();
			cout << "取出一个元素:" << command << endl;
			myguard.unlock();

			//...其他事务
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
	std::condition_variable my_cond;//生成一个条件变量对象
};

int main() {
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话

	//输出:入队出队各10000次后进入死循环,outMsg中while函数出不来了
	return 0;

}

notify_all

notify_one只通知一个线程,假如有2个out线程,1个in线程,那么in线程里的notify_one会随机唤醒其中一个out线程

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
using namespace std;

class A {
public:
	void inMsg() {
		for (int i = 0; i < 10000; i++) {		
			cout << "插入一个元素:" << i << endl;
			std::unique_lock<mutex>myguard(myMutex);
			myQueue.push(i);
			//假设outMsg正在处理一个事务,需要一段时间,而不是正卡在wait那里等你唤醒,那么这个notify_one就没意义
			my_cond.notify_one();//我们尝试把wait()的线程唤醒,执行完这行,那么outMsg()里边的wait就会被唤醒,唤醒之后的事情后续研究
		}
	}
	void outMsg() {
		int command;
		while (1) {
			std::unique_lock<std::mutex>myguard(myMutex);
			//wait用来等待一个东西
			//如果第二个参数lambda表达式返回值是true,那么wait()直接返回
			//如果第二个参数lambda表达式返回值是false,那么wait()将解锁unlock互斥量,并堵塞到本行
			//那堵塞到什么时候为止呢?堵塞到其他某个线程调用notify_one()成员函数为止
			//如果wait()没有第二个参数:my_cond.wait(myguard),那么就跟第二个参数lambda表达式返回false效果一样
			
			//当其他线程用notify_one()将本wait(原本是睡着/堵塞)的状态唤醒后,wait就开始恢复干活了,恢复后wait干什么活?
				//a)wait()不断地尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等待获取,如果获取到了锁(等于加了锁),那么wait就继续执行 b)
				//b)
					//b.1)如果wait有第二个参数(lambda)就判断这个lambda表达式,如果lambda表达式为false,那wait又对互斥量解锁,继续休眠在这里等待再次被notify_one唤醒
					//b.2)如果lambda表达式为true,则wait返回,流程走下来(此时互斥量锁被锁着)
					//b.3)如果wait没有第二个参数,则wait返回,流程走下来

			my_cond.wait(myguard, [this] {
				if (!this->myQueue.empty())
					return true;
				return false;
			});

			// ....
			// ....
			//流程只要能走到这里来,这个互斥锁一定是锁着的,同时myQueue肯定不为空

			command = myQueue.front();
			myQueue.pop();
			cout << "取出一个元素:" << command << "thread id = "<<std::this_thread::get_id() << endl;
			myguard.unlock();

			//...其他事务
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
	std::condition_variable my_cond;//生成一个条件变量对象
};

int main() {
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread outObj2(&A::outMsg, &myobj);
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	outObj2.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话

	//输出:入队出队各10000次后进入死循环,outMsg中while函数出不来了
	return 0;

}

在这里插入图片描述

notify_all会唤醒所有out线程,但是因为只有一个线程能拿到锁,所以输出差不多。只不过这次有一个线程是被唤醒着等待(休眠)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值