C++11多线程中关于unique_lock的介绍

一:unique_lock取代lock_guard

     unique_lock是个类模板,工作中,一般使用lock_guard;lock_guard取代了mutex的lock()和unlock()
     unique_lock比lock_guard灵活很多,虽然效率上差一点,内存占用多一点

二:unique_lock的第二个参数

  • std::adopt_lock:表示这个互斥量已经被lock了(你必须把互斥量提前lock了,否则会报异常)

         std::adopt_lock标记的效果就是“假设调用方线程已经拥有了互斥的所有权(已经lock()成功了)"
         通知lock_guard不需要在构造函数中lock这个互斥量了;
         用adopt_lock的前提是,你自己需要先把mutex先lock上

eg:

std::unique_lock<mutex> abguard1(my_mutex1,std::adopt_lock);

此时如果需要调用这条语句,则需要提前加锁,这条语句提供解锁功能。

  • std::try_to_lock

        我们会尝试用mutex的lock()去锁定这个mutex,但如果没有锁定成功,我也会立即返回,并不会阻塞在那里
        用这个try_to_lock的前提是你自己不能先去lock

eg:

std::unique_lock<mutex> abguard1(my_mutex1, std::try_to_lock);

即当有两个线程时,如果一个锁住的时间较长,另一个线程碰到这个锁的时候,可以用if语句跳过这个锁,往后面执行

  • std::defer_lock

        用这个std::defer_lock的前提是,你不能自己先lock,否则会报异常
        defer_lock的意思就是并没有给mutex加锁,初始了一个没有加锁的mutex

 使用std::defer_lock设置初始化的时候不进行默认的上锁操作;从而在使用时可以随时加锁和解锁,而且最后一个锁不用进行解锁。

三,unique_lock的成员函数

  1. lock(),加锁
  2. unlock(),解锁
  3. try_lock(),尝试去拿到锁,返回true则拿到锁
  4. release(),返回它所管理的mutex对象指针,并释放所有权,也就是说unique_lock和mutex不在有关系
    严格区分unlock()和release()的区别
    如果原来mutex对象处于加锁状态,则需要接管过来并且解锁。(release返回的是原视my_mutex的指针)

eg:

        std::unique_lock<mutex> abguard1(my_mutex1);

        此时ptr就是my_mutex1的指针
        mutex *ptr=abguard1.release();  //现在需要自己解锁my_mutex1
        ptr->unlock();

注:

    lock锁住的代码越少,执行越快,整个程序运行效率越高
    把锁头锁住的代码多少称为粒度,粒度一般用粗细进行表示
    a)锁住的代码越少,这个粒度越细,执行效率越高
    a)锁住的代码越多,这个粒度越粗,执行效率越低

四,unique_lock所有权的传递mutex

    unique_lock<mutex> abguard1(my_mutex1); //所有权问题
    abguard1可以把自己对mutex(my_mutex1)的所有权给其他unique_lock对象
    使用move,但是只能转移,不能复制

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

class A
{
public:
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 10000; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			//std::unique_lock<mutex> abguard1(my_mutex1,std::adopt_lock);
			//std::unique_lock<mutex> abguard1(my_mutex1, std::try_to_lock);
			//if (abguard1.owns_lock())
			//{
			std::unique_lock<mutex> abguard1(my_mutex1, std::defer_lock); //没有加锁的abguard1
			abguard1.lock();   //不用自己unlock

			//处理一些非共享的代码时,先unlock,然后再lock()
			//abguard1.unlock();
			//处理非共享代码
			//.......
			//abguard1.lock();    //这个lock不用再unlock,上面的unique_lock会帮助解锁

			msgRecvQueue.push_back(i);   //把收到的命令,放到消息队列中
			//}
		}
	}

	bool outMsgLUL(int &command)
	{
		std::unique_lock<mutex> abguard1(my_mutex1);

		//此时ptr就是my_mutex1的指针
		//mutex *ptr=abguard1.release();  //现在需要自己解锁my_mutex1
		//ptr->unlock();

		if (!msgRecvQueue.empty())
		{
			command = msgRecvQueue.front();  
			msgRecvQueue.pop_front();   
			return true;
		}
		return false;
	}

	//把数据从消息队列中取出的线程
	void outMsgRecvRueue()
	{
		int command = 0;
		for (int i = 0; i < 100000; ++i)
		{
			bool YN = outMsgLUL(command);
			if (YN)
			{
				cout << "outMsgRecvQueue()执行,取出一个元素" << command << endl;
				//可以考虑进行命令(数据)处理
				//....
			}
			else
			{
				//消息队列为空
				cout << "outMsgRecvQueue()执行,但是目前消息队列为空" << i << endl;
			}
		}
	}
private:
	list<int> msgRecvQueue;
	mutex my_mutex1;    //创建一个互斥量
};

int main()
{
	A a;
	thread test1(&A::outMsgRecvRueue, &a);//第二个参数是引用才能保证
	thread test2(&A::inMsgRecvQueue, &a);//第二个参数是引用才能保证
	test1.join();
	test2.join();

	//一:unique_lock取代lock_guard
	//unique_lock是个类模板,工作中,一般使用lock_guard;lock_guard取代了mutex的lock()和unlock()
	//unique_lock比lock_guard灵活很多,效率上差一点,内存占用多一点
	//二:unique_lock的第二个参数
	//(2.1)std::adopt_lock:表示这个互斥量已经被lock了(你必须把互斥量提前lock了,否则会报异常)
	//std::adopt_lock标记的效果就是“假设调用方线程已经拥有了互斥的所有权(已经lock()成功了)"
	//通知lock_guard不需要在构造函数中lock这个互斥量了;
	//用adopt_lock的前提是,你自己需要先把mutex先lock上

	//(2.2)std::try_to_lock
	//我们会尝试用mutex的lock()去锁定这个mutex,但如果没有锁定成功,我也会立即返回,并不会阻塞在那里
	//用这个try_to_lock的前提是你自己不能先去lock

	//(2.3)std::defer_lock
	//用这个std::defer_lock的前提是,你不能自己先lock,否则会报异常
	//defer_lock的意思就是并没有给mutex加锁,初始了一个没有加锁的mutex
	//
	//三,unique_lock的成员函数
	//(3.1)lock(),加锁
	//(3.2)Unlock(),解锁
	//(3.3)try_lock(),尝试去拿到锁,返回true则拿到锁
	//(3.4)release(),返回它所管理的mutex对象指针,并释放所有权,也就是说unique_lock和mutex不在有关系
	//严格区分unlock()和release()的区别
	//如果原来mutex对象处于加锁状态,则需要接管过来并且解锁。(release返回的是原视my_mutex的指针)
 //   lock锁住的代码越少,执行越快,整个程序运行效率越高
	//把锁头锁住的代码多少称为粒度,粒度一般用粗细进行表示
	//a)锁住的代码越少,这个粒度越细,执行效率越高
	//a)锁住的代码越多,这个粒度越粗,执行效率越低

	//四,unique_lock所有权的传递mutex
	//unique_lock<mutex> abguard1(my_mutex1); //所有权问题
	//abguard1可以把自己对mutex(my_mutex1)的所有权给其他unique_lock对象
	//使用move,但是只能转移,不能复制



	system("pause");
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大学生毕设

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值