专业编程基础技术教程

网站首页 > 基础教程 正文

记录:学习多线程(七)(多线程入门)

ccvgpt 2024-07-26 00:48:08 基础教程 9 ℃

记录:学习多线程(七):condition_variable、wait、notify_one、notify_all、

条件变量std::condition_variable、wait()、notify_one()、

上述代码深入思考

记录:学习多线程(七)(多线程入门)

notify_all()

#include<map>
#include<string>
#include<thread>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

class A{
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue(){//unlock()
		for(int i=0;i<100000; ++i){
			std::unique_lock<std::mutex> sbguard1(my_mutex1);
			cout<<"inMsgRecvQueue()执行,插入一个元素"<<i<<endl;
			msgRecvQueue.push_back(i);/*假设这个数字i就是我们收到的*/
			/*加入outMsgRecvQueue()正在处理一个事务,需要一段时间,而
			不是正卡在wait()那里等你唤醒,那么此时notify_one()这个调用
			没有效果*/
			my_cond.notify_all();/*我们尝试把wait()唤醒,执行完这行,那么outMsgRecvQueue里边的wait()就会被唤醒;(只能通知一个线程)*/
		}//end for
		return;
	}

	bool outMsgLULproc(int &command){
	/*双重锁定,双重检查*/
			if(!msgRecvQueue.empty()){
				std::unique_lock<std::mutex> sbguard1(my_mutex1);
				if(!msgRecvQueue.empty()){
					//消息队列不为空
					command = msgRecvQueue.front();/*返回第一个元素
					,但不检查元素是否存在*/
					msgRecvQueue.pop_front();//移除第一个元素,但不返回;
					return true;
				}else{
					//sleep(100);
					cout<<"outMsmRecvQueue()执行,但目前消息队列为空"<<i<<endl;
				}
			}
			return false;
	}
	
	//把数据从消息队列中取出的线程
	void outMsgRecvQueue(){
		int command = 0;
		whlie(true){
			std::unique_lock<std::mutex> sbguard1(mu_mutex1);
			
			/*wait()用来等一个东西*/
			/*如果第二个参数返回true,那么wait()直接返回,如果第二个参数
			的lambda表达式返回值是false,那么wait()将解锁互斥量,并堵塞
			到本行,那堵塞到什么时候为止呢?堵塞到其他某个线程调用
			notify_one()成员函数为止,如果wait()没有第二个参数,
			my_cond.wait(sbguard1);那么就跟第二个参数lambda表
			达式返回false效果一样,当其他线程用notify_one将本wait()
			(原本是睡着/堵塞)的状态唤醒后,wait就开始恢复干活了,恢复
			后wait干什么活?
			a//wait不断的尝试获得互斥量锁,如果获取不到,
			那么流程就卡在wait()这里等着获取,如果获取到了锁,那么wait就
			继续执行
			b//上锁(实际上,获取到了锁就等于上了锁。)
			  b.1//如果wait有第二个参数,就判断lanbda表达式,如果lambda
			表达式为false,那么wait()又对互斥量解锁,然后又休眠这里等待
			再次被notify_oen()唤醒
			  b.2//如果表达式为true,则wait()返回流程走下来,此时互斥锁
			被锁着。
			  b.3//如果wait没有第二参数,则wait返回,流程走下去。*/
			
			
			my_cond.wait(sbguard1,[this]{/*一个lambda表达式就是一个
			调用对象*/
				if(!msgRecvQueue.empty())
					return true;
				return false;
			});
			/*只要流程能走下来,这个互斥量一定是被锁着的,同时
			msgRecvQueue至少有一条数据*/
			command = msgRecvQueue.front();
			msgRecvQueue.pop_front();
			cout<<"outMsgRecvQueue()执行,取出一个元素"<<command<<"threadid="<<std::this_thread::get_id()<<endl;
			sbguard1.unlock();/*因为unique_lock的灵活性,我们可以随时
			的解锁,以免锁住太长时间*/
			//执行一些具体的动作
		}//end while
	}

private:
	std::list<int> msgRecvQueue: //容器,专门用于代表玩家给咱们发送过来的命令
	std::mutex my_mutex1;//创建一个互斥量,一个互斥量是一把锁
	std::condition_variable mycond;//生成一个条件变量对象
};

int main(){
	A myobja;
	std::thread myOutMsgObj(&A::outMsgRecvQueue,&myobja);/*第二个参数
	是引用,才能保证线程里用的是用一个对象*/
	std::thread myOutMsgObj2(&A::outMsgRecvQueue,&myobja);
	std:;thread myInMsgObj(&A::inMsgRecvQueue,&myobja);
	myOutMsgObj.join();
	myOutMsgObj2.join();
	myInMsgObj.join();
	
	return 0;
}

//条件变量std::condition_variable、wait()、notify_one()、

//线程A:等待一个条件满足

//线程B:专门往消息队列中扔消息(数据)

//std::condition_variable实际上是一个类,是一个和条件相关的一个类,说白了就是等待要给条件达成。

//这个类需要和互斥量来配合工作,用的时候我们要生成这个类的对象‘

//上述代码的深入思考

//notify_all()

Tags:

最近发表
标签列表