unique_lock详解

        unique_lock可以取代lock_guard。

#include<thread>
#include<iostream>
#include<list>
#include<mutex>

using namespace std;

class A
{
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			std::unique_lock<std::mutex> sbguard1(my_mutex);
			msgRecvQueue.push_back(i); //假设这个数字就是收到的命令,直接放到消息队列里来
			//.....
			//其他处理代码
		}
		return;
	}

	bool outMsgLULProc(int& command)
	{
		std::unique_lock<std::mutex> sbguard1(my_mutex);
		if (!msgRecvQueue.empty())
		{
			//消息不为空			
			command = msgRecvQueue.front(); //返回第一个元素,但不检查元素是否存在;
			msgRecvQueue.pop_front();  //移除第一个元素,但不返回;
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i < 100; ++i)
		{
			bool result = outMsgLULProc(command);
			if (result == true)
			{
				cout << "outMsgRecvQueue()执行了,从容器中取出一个元素" << command << endl;
				//可以考虑进行命令(数据)处理
				//....
			}
			else
			{
				//消息对列为空
				cout << "outMsgRecvQueue()执行了,但目前收消息队列中是空元素" << i << endl;
			}
		}
		cout << "end" << endl;
	}
private:
	std::list<int>  msgRecvQueue; //容器(收消息队列),专门用于代表玩家给咱们发送过来的命令
	std::mutex my_mutex; //创建互斥量
};

int main()
{
	{
		A  myobja;
		std::thread myOutnMsgObj(&A::outMsgRecvQueue, &myobja);  //注意这里第二个参数必须是引用(用std::ref也可以),才能保证线程里用的是同一个对象
		std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
		myInMsgObj.join();
		myOutnMsgObj.join();
		cout << "main主函数执行结束!" << endl;
	}

	return 0;
}

 

unique_lock的第二个参数

1、std::adopt_lock

使用std::adopt_lock的前提是开发者需要先把互斥量lock上。

#include<thread>
#include<iostream>
#include<list>
#include<mutex>

using namespace std;

class A
{
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
            my_mutex.lock();
			std::unique_lock<std::mutex> sbguard1(my_mutex, std::adopt_lock);
			msgRecvQueue.push_back(i); //假设这个数字就是收到的命令,直接放到消息队列里来
			//.....
			//其他处理代码
		}
		return;
	}

	bool outMsgLULProc(int& command)
	{
		my_mutex.lock();
	    std::unique_lock<std::mutex> sbguard1(my_mutex, std::adopt_lock);
		if (!msgRecvQueue.empty())
		{
			//消息不为空			
			command = msgRecvQueue.front(); //返回第一个元素,但不检查元素是否存在;
			msgRecvQueue.pop_front();  //移除第一个元素,但不返回;
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i < 100; ++i)
		{
			bool result = outMsgLULProc(command);
			if (result == true)
			{
				cout << "outMsgRecvQueue()执行了,从容器中取出一个元素" << command << endl;
				//可以考虑进行命令(数据)处理
				//....
			}
			else
			{
				//消息对列为空
				cout << "outMsgRecvQueue()执行了,但目前收消息队列中是空元素" << i << endl;
			}
		}
		cout << "end" << endl;
	}
private:
	std::list<int>  msgRecvQueue; //容器(收消息队列),专门用于代表玩家给咱们发送过来的命令
	std::mutex my_mutex; //创建互斥量
};

int main()
{
	{
		A  myobja;
		std::thread myOutnMsgObj(&A::outMsgRecvQueue, &myobja);  //注意这里第二个参数必须是引用(用std::ref也可以),才能保证线程里用的是同一个对象
		std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
		myInMsgObj.join();
		myOutnMsgObj.join();
		cout << "main主函数执行结束!" << endl;
	}

	return 0;
}

2、std::try_to_lock

使用std::try_to_lock的前提是开发者不可以自己把互斥量lock上。

#include<thread>
#include<iostream>
#include<list>
#include<mutex>

using namespace std;

class A
{
public:
	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;

			//std::unique_lock<std::mutex> sbguard1(my_mutex, std::adopt_lock);
			//std::unique_lock<std::mutex> sbguard1(my_mutex);
			std::unique_lock<std::mutex> sbguard1(my_mutex, std::try_to_lock);
			if (sbguard1.owns_lock()) //条件成立表示拿到了锁头
			{
				//拿到了锁头,离开sbguard1作用域锁头会自动释放
				msgRecvQueue.push_back(i); //假设这个数字就是收到的命令,直接放到消息队列里来
			//.....
			//其他处理代码
			}
			else
			{
				//没拿到锁
				cout << "inMsgRecvQueue()执行,但没拿到锁,只能干点别的事" << i << endl;
			}
		}
	}

	bool outMsgLULProc(int& command)
	{
		std::unique_lock<std::mutex> sbguard1(my_mutex);
		std::chrono::milliseconds dura(20000);  //定义一个时间相关对象,初值2万,单位毫秒, 卡在这里20秒
		std::this_thread::sleep_for(dura);

		if (!msgRecvQueue.empty())
		{
			//消息不为空			
			command = msgRecvQueue.front(); //返回第一个元素,但不检查元素是否存在;
			msgRecvQueue.pop_front();  //移除第一个元素,但不返回;
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i < 100000; ++i)
		{
			bool result = outMsgLULProc(command);
			if (result == true)
			{
				cout << "outMsgRecvQueue()执行了,从容器中取出一个元素" << command << endl;
				//可以考虑进行命令(数据)处理
				//....
			}
			else
			{
				//消息对列为空
				cout << "outMsgRecvQueue()执行了,但目前收消息队列中是空元素" << i << endl;
			}
		}
		cout << "end" << endl;
	}
private:
	std::list<int>  msgRecvQueue; //容器(收消息队列),专门用于代表玩家给咱们发送过来的命令
	std::mutex my_mutex; //创建互斥量
	std::mutex my_mutex2; //创建互斥量
};

int main()
{
	{
		A  myobja;
		std::thread myOutnMsgObj(&A::outMsgRecvQueue, &myobja);  //注意这里第二个参数必须是引用(用std::ref也可以),才能保证线程里用的是同一个对象
		std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
		myInMsgObj.join();
		myOutnMsgObj.join();
		cout << "main主函数执行结束!" << endl;
	}

	return 0;
}

3、std::defer_lock

使用defer_lock的前提是开发者不能自己吧互斥量lock上,否则会报异常

unique_lock的成员函数

1、lock

给互斥量加锁,如果无法拿到锁,会阻塞一直等待拿到锁。

	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100000; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
            std::unique_lock<std::mutex> sbguard1(my_mutex, std::defer_lock);
			sbguard1.lock(); //反正unique_lock能自动解锁,不用自己解,所以这里只管加锁
			msgRecvQueue.push_back(i);
        }
    }

2、unlock

针对加锁的互斥量,给该互斥量解锁,不可以针对没加锁的互斥量使用,否则会报异常。

 3、try_lock

尝试给互斥量加锁,如果拿不到锁,则返回false;如果拿到了锁,则返回true。这个成员函数不阻塞。

	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100000; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			std::unique_lock<std::mutex> sbguard1(my_mutex, std::defer_lock);
			if (sbguard1.try_lock() == true) //返回true表示拿到了锁,自己不用管unlock问题
			{
				msgRecvQueue.push_back(i);
			}
			else
			{
			    cout << "抱歉,没拿到锁,做点别的事情吧!" << endl;
			}
        }
    }

4、release

	//把收到的消息(玩家命令)入到一个队列的线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100000; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			std::unique_lock<std::mutex> sbguard1(my_mutex);	//mutex锁定
			std::mutex* p_mtx = sbguard1.release();    //现在关联关系解除,程序员有责任自己解锁了,其实这个就是my_mutex,现在sbguard1已经不和my_mutex关联了(可以设置断点并观察)
			msgRecvQueue.push_back(i);
			p_mtx->unlock();//因为前面已经加锁,所以这里要自己解锁了	
        }
        return;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值