unique_lock学习
使用unique_lock 取代 lock_guard
-
unique_lock是个类模板,一般情况lock_guard满足需求,lock_guard取代mutex的lock()和unlock()。
但是unique_lock要比lock_guard灵活的多,但内存占用多,效率差点。 -
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 这个mutex2.2 std::try_to_lock
尝试mutex的lock()去锁这个mutex,若没有成功,立即返回,不会阻塞。
try_to_lock的前提是不能先lock。2.3 std::defer_lock
不能先lock
defer_lock的意思,并没有给mutex加锁,初始化一个没有加锁的mutex。 -
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()锁住的代码越少,执行越快,整个程序运行效率越高 粒度描述:粒度细、粗
- 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);
- uinque_lock所有权的传递,unique_lock管理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;
}