C++多线程开发(第四节)互斥量的概念,用法,死锁演示

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


//线程入口函数
void myprint(int num)
{
	cout << "线程开始了:" << num << endl;

	cout << "线程结束了" << num << endl;

	return;

}

class A {
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{

		for (int i = 0; i < 100000; i++)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			my_mutex.lock();
			msgRecvQueue.push_back(i);
			my_mutex.unlock();
		}
	}
	bool outMsgLULproc(int &command)
	{
		lock_guard<mutex>sbguard(my_mutex);//guard就相当于是一个模板,用mutex来对guard进行实例化
		                                   //sbguard是起的对象名
		                                   //lock_guard构造函数里面执行mutex::lock()
		                                   //lock_guard析构函数执行unlock
										   // 在guard保护的区域内操作共享数据
		//my_mutex.lock();

		my_mutex.lock();//锁的顺序一样,不会死锁
		my_mutex2.lock();

		//my_mutex2.lock();//锁的顺序不一样,会发生死锁
		//my_mutex.lock();
		if (!msgRecvQueue.empty())
		{
			int command = msgRecvQueue.front();
			msgRecvQueue.pop_front();//移除第一个元素,但是不返回
			//这里就考虑处理数据
			//my_mutex.unlock();
			return true;
		}
		//my_mutex.unlock();
		return false;
	}

	//把数据从消息队列中取出的过程
	void outMsgRecvQueue()
	{
		int commond = 0;
		if(outMsgLULproc(commond))
		for (int i = 0; i < 100000; i++)
		{
			if (outMsgLULproc(commond))
			{
				cout << "成功从队列中取出元素:" << commond << endl;
			}
			else
			{
				cout << "消息队列为空" << i << endl;
			}

		}
		cout << "end" << endl;
	}
private:
	std::list<int>msgRecvQueue;//容器,消息队列,专门用来代表玩家发送过来的命令。
	std::mutex my_mutex;//创建一个互斥量
	std::mutex my_mutex2;//创建第二个互斥量(用来演示死锁问题)
};

int main()
{
	//a:多个线程的执行顺序是混乱的,跟操作系统内部对线程的运算调度机制有关
	//b:主线程等待所有子线程运行结束,主线程最后结束(join)
	//c:我们将thread拖拽到容器内进行管理,看起来像一个thread对象数组,这对我们一次性创建大量线程有帮助
	vector<thread>mythreads;//创建多个线程
	A myobja;

	thread myoutn(&A::outMsgRecvQueue, &myobja);
	thread myinn(&A::inMsgRecvQueue, &myobja);
	myoutn.join();
	myinn.join();
		/*for (int i = 0; i < 10; i++)
	{
		mythreads.push_back(thread(myprint, i));
	}
	for (int i = 0; i < 10; i++)
	{
		mythreads[i].join();
	}*/
	
	/*for (auto iter = mythreads.begin(); iter != mythreads.end(); iter++)进程阻塞
	{
		iter->join();
	}*/
	cout << "主线程结束" << endl;

	//保护共享数据,操作时,某个线程用代码把共享数据锁住,操作数据,解锁
	//其他想操作共享数据的线程必须等待解锁,锁定住,操作,解锁

    //互斥量
	//一:互斥量的基本概念
	//互斥量是个类对象。理解成一把锁,多个线程尝试用lock()成员函数来加锁这把锁头,只有一个线程能够锁定成功(成功的标志)
	                   //如果没锁成功,那末流程卡在lock()这里不断尝试去锁这把锁头
	//互斥量使用的时候要小心,保护数据不多也不少,少了,没达到保护效果,多了,影响效率

	//互斥量的用法
	//(2.1)lock(),unlock()
	//步骤:先lock(),操作共享数据,unlock()
	//lock()和unlock()要成对使用,有lock必然要有unlock,
	//为了防止大家忘记unlock,引入了一个叫std::lock_guard的类模板:你忘记unlock不要紧,我替你unlock
	//学习过智能指针(unique_ptr<>),你忘记释放内存不要紧,我来释放
	//(2.2) std::lock_guard类模板,直接取代lock和unlock(不能再用lock和unlock)


	//死锁
	//有金银两个锁头,进程A先拿到金锁头,进程B先拿到银锁头,但是拿完后两个线程都想要对方的锁头,此时两个线程也并没有解锁,导致两个进程卡死,造成死锁
	//死锁的解决方法
	//保证两个锁的顺序相同
	
	//1:std::lock(函数模板,用来处理多个互斥量的时候才出场)
	//能力;一次锁住两个或者两个以上的互斥量(至少两个)
    //如果互斥量中有一个没锁住,它就在哪里等着,等所有互斥量都锁柱,它才能能往下走
	//如果只是锁了一个,另外一个没锁柱,则它立即把锁住的解锁

	


	system("pause");
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值