4 —— unique_lock详解

一 unique_lock取代lock_guard

  unique_lock是个类模板,工作中,一般使用lock_guard。因为unqiue_lock占用的内存更多,效率底一些。但是unique_lock更加灵活,它的构造函数的第二个参数可以有其它的形式,下面会提到。同时,uniuqe_lock与lock_guard一样自动对绑定的互斥量自动加锁,解锁。

二 unique_lock的构造函数

  1. std::adopt_lock
    表示被绑定的互斥量已经被lock(),同lock_guard中一样。假设mutex已经lock成功了,再来使用。
  2. std::try_to_lock
    尝试使用mutex.lock()去锁住保护数据,如果没有锁成功,也会立即返回。流程不会阻塞,会继续进行下去。用std::try_to_lock的前提是你不能将mutex先锁住。示例:
	// 把收到的消息传入队列
	void inMsgRecvQueue()
	{
		for (size_t i = 0; i < 1000; ++i)
		{
			cout << "收到消息,并放入队列 " << i << endl;

			unique_lock<mutex> my_uniq(my_mutex, std::try_to_lock);	//在另一线程等待时,这个线程不会阻塞,等待mutex加锁。	
			
			if (my_uniq.owns_lock())	//	判断是否获得锁
			{
				msgRecvQueue.push_back(i);
			}
			else
			{
				cout << i << "入队时没有获得锁" << endl;
			}
		}

		cout << "消息入队结束" << endl;
	}

	// 从队列中取出消息
	void outMsgRecvQueue()
	{
		for (size_t i = 0; i < 1000; ++i)
		{
			unique_lock<mutex> my_uniq(my_mutex);
			std::chrono::milliseconds dura(2 * 1000); // 2秒
			std::this_thread::sleep_for(dura); // 等待2秒

			if (!msgRecvQueue.empty())
			{
				// 队列不为空
				int num = msgRecvQueue.front();
				cout << "从消息队列中取出 " << num << endl;
				msgRecvQueue.pop_front();
			}
			else
			{
				// 消息队列为空
				cout << "消息队列为空 " << endl;
			}
		}

		cout << "消息出队结束" << endl;
	}
  1. std::defer_lock
    使用std::defer_lock的前提和std::try_to_lock一样,你不能提前对mutex lock()。它的意思是,初始化了一个没有加锁的mutex。通过这个参数,可以调用unique_lock的成员函数,来提前程序的灵活性,让锁的粒度越细。

  那 … 什么是锁的粒度?

锁的粒度:有人把锁头锁住的代码的多少,叫作锁的粒度。粒度用粗细来描述。
锁住的代码量越少,粒度就越细,但是可能保护数据的安全。选择一个合适的粒度是高级程序员实力的体现。

举例:

			unique_lock<mutex> my_uniq(my_mutex, std::defer_lock);	
			
			my_uniq.lock();	// 加锁

			// 处理共享数据....

			my_uniq.unlock();

			// 处理非共享数据....

			my_uniq.lock();

			// 再处理共享数据....

三 unique_lock的成员函数

  1. lock()
    对mutex加锁
  2. unlock()
    对mutex解锁
  3. try_lock()
    与std::defer_lock一起使用,作用同std::try_to_lock一样,一直尝试会获得锁,如果没有获得,则返回false。示例:
	// 把收到的消息传入队列
	void inMsgRecvQueue()
	{
		for (size_t i = 0; i < 10000; ++i)
		{
			cout << "收到消息,并放入队列 " << i << endl;

			unique_lock<mutex> my_uniq(my_mutex, std::defer_lock);	
			
			if (my_uniq.try_lock() == true)	//如果取到锁
			{
				msgRecvQueue.push_back(i);
			}
			else
			{
				cout << i << "入队没有取得锁" << endl;
			}

		}

		cout << "消息入队结束" << endl;
	}
  1. release()
    返回它所管理的mutex对象指针,并释放所有权,也就是说,unique_lock与mutex不再有联系。如果之前mutex已经加锁,则要记得unlock()。示例:
	// 从队列中取出消息
	void outMsgRecvQueue()
	{
		for (size_t i = 0; i < 10000; ++i)
		{
			unique_lock<mutex> my_uniq(my_mutex);
			std::mutex *ptx = my_uniq.release();	//	解除了mutex,要自己负责mutex的unlock()

			if (!msgRecvQueue.empty())
			{
				// 队列不为空
				int num = msgRecvQueue.front();
				cout << "从消息队列中取出 " << num << endl;
				msgRecvQueue.pop_front();
			}
			else
			{
				// 消息队列为空
				cout << "消息队列为空 " << endl;
			}

			ptx->unlock();	//	这一步不能忘记
		}

		cout << "消息出队结束" << endl;
	}

四 unique_lock的所有权转移

unique_lock所有权:unique_lock对象可以将绑定的mutex转交给其它unique_lock对象。

有两种方式:1 ,同unique_ptr一样,通过移动构造函数(不能通过拷贝构造函数)拷贝

			unique_lock<mutex> my_uniq1(my_mutex);
			unique_lock<mutex> my_uniq2(std::move(my_uniq1));

2,将unique_lock作为函数返回值。

	std::unique_lock<mutex> rtn_unique_lock()
	{
		 std::unique_lock<std::mutex> tmp_uniq(my_mutex);
		 return tmp_uniq;
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值