互斥量概念、用法、死锁演示及解决详解

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

一、互斥量(mutex)的基本概念

互斥量就是个类对象,可以理解为一把锁,多个线程尝试用lock()成员函数来加锁,只有一个线程能锁定成功(成功的标志是lock()函数返回),如果没有锁成功,那么流程将卡在lock()这里不断尝试去锁定。
互斥量使用要小心,保护数据不多也不少,少了达不到效果,多了影响效率。

二、互斥量的用法

包含mutex 头文件(好像也可以不加)

2.1 lock(),unlock()

步骤:1.lock(),2.操作共享数据,3.unlock()。
lock()和unlock()要成对使用,有lock()必然要有unlock,每调用一次lock(),必然应该调用一次unlock();
不应该也不允许调用1次lock()却调用了2次unlock(),也不允许调用2次lock()却调用1次unlock(),这些非对称数量的调用都会导致代码的不稳定甚至崩溃

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

class A
{
   
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
   
		for (int i = 0; i < 100000; ++i)
		{
   
			cout << "inMsgReceiveQueue 执行,插入一个元素" << i << endl;
			
			//数字i即为服务器收到的命令,插入到list中,即收到十万个玩家不断向消息队列中发玩家命令
			my_mutex.lock();
			msgReceiveQueue.push_back(i);
			my_mutex.unlock();
		}
		return;
	}

	bool outMsgLULProc(int &command) {
   
		my_mutex.lock();
		if (!msgReceiveQueue.empty())
		{
   
			//消息不为空,则取出数据
			command = msgReceiveQueue.front();//返回第一个元素,但不检查元素是否存在
			msgReceiveQueue.pop_front(); //移除第一个元素,但不返回
			my_mutex.unlock();
			return true;
		}
		my_mutex.unlock();
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
   
		int command = 0;
		for (int i = 0; i < 100000; ++i)
		{
   
			bool result = outMsgLULProc(command);
			if (result == true) {
   
				cout << "outMsgRecvQueue()执行,取出一个元素" << endl;
			}
			else {
   
				//消息队列为空
				cout << "目前消息队列为空" << i << endl;
			}
		}
		cout << "end" << endl;
	}


private:
	list<int> msgReceiveQueue; //list容器,用于代表玩家发送给服务器的命令
	mutex my_mutex;//创建了一个互斥量
};


int main()
{
   
	//用成员函数作为线程的方法来写线程
	A myobja;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobja); //取对象的地址传参(可以理解为引用)
	thread myInMsgObj(&A::inMsgRecvQueue, &myobja);

	myInMsgObj.join();
	myOutMsgObj.join();
	//程序运行会引发异常,因为没有锁住共享数据,解决这个问题,需要引入互斥量
	cout << "I Love China" << endl;//最后执行这句,整个进程退出

	return 0;
}
2.2 lock_guard类模板

lock_guard guard(myMutex);直接取代lock()和unlock(),也就是说用了lock_guard之后,再不能使用lock()和unlock()了
lock_guard构造函数执行了mutex::lock();在作用域结束时,调用析构函数,执行mutex::unlock()

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

class A
{
   
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
   
		for (int i = 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值