C++多线程学习笔记05(unique_lock )

unique_lock学习

使用unique_lock 取代 lock_guard

  1. unique_lock是个类模板,一般情况lock_guard满足需求,lock_guard取代mutex的lock()和unlock()。
    但是unique_lock要比lock_guard灵活的多,但内存占用多,效率差点。

  2. unique_lock的第二个参数
    2.1 std::lock_guardstd::mutex sbguard(my_tuex,std::adopt_lock); //adopt_lock标记作用
    std::adopt_lock表示这个互斥量已经被lock了(提前是必须lock,否则报异常)
    unique_lock 带std::adopt标记,含义相同,不希望再unique_lock()的构造函数中lock 这个mutex

    2.2 std::try_to_lock
    尝试mutex的lock()去锁这个mutex,若没有成功,立即返回,不会阻塞。
    try_to_lock的前提是不能先lock

    2.3 std::defer_lock
    不能先lock
    defer_lock的意思,并没有给mutex加锁,初始化一个没有加锁的mutex。

  3. unique_lock的成员函数
    3.1 lock()加锁
    3.2 unlock()解锁
    3.3 try_lock()尝试给互斥量加锁,如果拿不到锁,则返回false,如果拿到返回true,这个是不阻塞的。
    3.4 release() 返回它管理的对象指针,释放所有权,也就是uinque_sock与mutex 不再有关系。
    如果原来mutex对象处于加锁状态,要负责接管过来并负责解锁。
    std::mutex *pt = sbguard1.release(); 返回原始指针

    lock()锁住的代码越少,执行越快,整个程序运行效率越高 粒度描述:粒度细、粗

    1. uinque_lock所有权的传递,unique_lock管理mutex。
      std::unique_lockstd::mutex sbguard1(my_mutex1); // sbguard1拥有my_mutex1的所有权 可以转移其他的unique_lock对象 , 但是不能复制.
      4.1 std::move std::unique_lockstd::mutex sbguard2(std::move(sbguard1)); //sbguard1 指向空 ,sbguard2指向my_mutex1
      4.2 return std::unique_lock(std::mutex);

std::adopt_lock使用

// 线程3.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

class A {
public:
	//把收到的消息(玩家命令)写入到一个队列线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i<10000; i++)
		{
			cout << "inMesRecvQueue()执行,插入元素" << i << endl;
			{
				my_mutex1.lock();
				std::unique_lock<std::mutex> sbguard1(my_mutex1, std:: adopt_lock);
				msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队列
			}
		}
	}


	bool outMsgLULProc(int &command)
	{
		my_mutex1.lock();
		std::unique_lock<std::mutex>sbguard1(my_mutex1,std::adopt_lock);
		std::chrono::microseconds dura(200);
		std::this_thread::sleep_for(dura);  //休息一定时间
		if (!msgRecvQueue.empty())
		{
			//消息不为空
			command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
			msgRecvQueue.pop_front();//移除第一个元素,但不返回
		  //这里是处理数据....
		  //cout << "处理数据" << command << endl;		
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i<10000; i++)
		{
			bool result = outMsgLULProc(command);
			if (result)
				cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
			}
		}
		cout << "消息队列处理完成" << endl;
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	mutex my_mutex2;//创建互斥量
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
	return 0;

}

std::defer_lock使用

// 线程3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

class A {
public:
	//把收到的消息(玩家命令)写入到一个队列线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i<10000; i++)
		{
			cout << "inMesRecvQueue()执行,插入元素" << i << endl;
			{
				std::unique_lock<std::mutex> sbguard1(my_mutex1, std::defer_lock);//创建没有加锁的mutex
				sbguard1.lock();//不用自己加unlock()
				msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队列
			}
		}
	}
	bool outMsgLULProc(int &command)
	{
		my_mutex1.lock();
		std::unique_lock<std::mutex>sbguard1(my_mutex1,std::adopt_lock);
		std::chrono::microseconds dura(200);
		std::this_thread::sleep_for(dura);  //休息一定时间
		if (!msgRecvQueue.empty())
		{
			//消息不为空
			command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
			msgRecvQueue.pop_front();//移除第一个元素,但不返回
		  //这里是处理数据....
		  //cout << "处理数据" << command << endl;				
			return true;
		}
		return false;
	}
	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i<10000; i++)
		{
			bool result = outMsgLULProc(command);
			if (result)
				cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
			}
		}
		cout << "消息队列处理完成" << endl;
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	mutex my_mutex2;//创建互斥量
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
	return 0;

}

std::defer_lock使用2 unlock(),lock()

// 线程3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

class A {
public:
	//把收到的消息(玩家命令)写入到一个队列线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i<10000; i++)
		{
			cout << "inMesRecvQueue()执行,插入元素" << i << endl;
			{
				std::unique_lock<std::mutex> sbguard1(my_mutex1, std::defer_lock);//创建没有加锁的mutex
				sbguard1.lock();//不用自己加unlock()
				//因为处理共享代码
				sbguard1.unlock();
				//处理共享代码
				sbguard1.lock();
				//处理共享代码
				msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队列
		
			}
		}
	}
	bool outMsgLULProc(int &command)
	{
		my_mutex1.lock();
		std::unique_lock<std::mutex>sbguard1(my_mutex1,std::adopt_lock);
		std::chrono::microseconds dura(200);
		std::this_thread::sleep_for(dura);  //休息一定时间

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

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i<10000; i++)
		{
			bool result = outMsgLULProc(command);
			if (result)
				cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
			}
		}
		cout << "消息队列处理完成" << endl;
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	mutex my_mutex2;//创建互斥量
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
	return 0;
}

std::defer_lock使用3 try_lock(),owns_lock()

// 线程3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

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

				std::unique_lock<std::mutex> sbguard1(my_mutex1, std::defer_lock);//创建没有加锁的mutex

				if (sbguard1.try_lock() == true) //返回true 拿到锁
				{
					msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队列
				}
				else
				{
					cout << "****inMsgRecvQueue()执行没拿到锁" << endl;
				}
				
				//if (sbguard1.owns_lock())
				//{
				//	//拿到锁
				//msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队列  
				//}
				//else
				//	cout << "****inMsgRecvQueue()执行没拿到锁" << endl;
			}
		}
	}

	bool outMsgLULProc(int &command)
	{
		my_mutex1.lock();
		std::unique_lock<std::mutex>sbguard1(my_mutex1,std::adopt_lock);
		std::chrono::microseconds dura(200);
		std::this_thread::sleep_for(dura);  //休息一定时间

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

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i<10000; i++)
		{
			bool result = outMsgLULProc(command);
			if (result)
				cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
			}
		}
		cout << "消息队列处理完成" << endl;
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	mutex my_mutex2;//创建互斥量
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
	return 0;

}

unique_lock的成员函数 .release()

// 线程3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

class A {
public:
	//把收到的消息(玩家命令)写入到一个队列线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i<10000; i++)
		{
			cout << "inMesRecvQueue()执行,插入元素" << i << endl;
			{
				std::unique_lock<std::mutex> sbguard1(my_mutex1);
				std::mutex *pt = sbguard1.release(); 
				pt->unlock();
			}
		}
	}
	bool outMsgLULProc(int &command)
	{
		my_mutex1.lock();
		std::unique_lock<std::mutex>sbguard1(my_mutex1,std::adopt_lock);
		std::chrono::microseconds dura(200);
		std::this_thread::sleep_for(dura);  //休息一定时间

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

			msgRecvQueue.pop_front();//移除第一个元素,但不返回
		  //这里是处理数据....
		  //cout << "处理数据" << command << endl;
									
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i<10000; i++)
		{
			bool result = outMsgLULProc(command);
			if (result)
				cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
			}
		}
		cout << "消息队列处理完成" << endl;
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	mutex my_mutex2;//创建互斥量
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值