C++ unique_lock详解

头文件<mutex>

unique_lock
相比于lock_guard,更灵活,但效率上差一点,内存也占用更多.
在这里插入图片描述
可以看到unique_lock也含有第二个参数的构造函数.常规使用和lock_guard没什么区别。

std::try_to_lock()

std::try_to_lock()会尝试加锁,使用前不能自己lock()
使用方法如下:

class A
{
private:
	list<int>msgqueue;
	mutex mymutex1;

public:
	void MsgEnqueue()
	{

		for (int i = 0; i < 10000; ++i)
		{

			cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
			unique_lock<mutex>l(mymutex1,std::try_to_lock);
			if (l.owns_lock())
			{
				msgqueue.push_back(i);
			}
			else
			{
				cout << "MsgEnqueue执行,但是没有拿到锁 : " << i << endl;
			}

		}
		return;
	}
	bool helper(int & command)
	{

		unique_lock<mutex>mylock (mymutex1);
		chrono::microseconds d(2000);
		this_thread::sleep_for(d);

		if (!msgqueue.empty())
		{
			command = msgqueue.front();
			msgqueue.pop_front();
			return true;
		}
		return false;
	}
	void MsgDequeue()
	{
		int command = 0;
		for (int i = 0; i < 10000; ++i)
		{
			bool result = helper(command);
			if (result)
			{
				cout << "helper执行,取出一个元素 " << command << endl;
			}
			else
			{
				cout << "MsgEnqueue()执行,但队列为空 " <<  i <<endl;
			}

		}
	}
};
int main()
{
	A a;
	thread t1(&A::MsgEnqueue, &a);
	thread t2(&A::MsgDequeue, &a);
	t1.join();
	t2.join();
	cout << endl;
}

在这里插入图片描述

defer_lock()

使用defer_lock(),前提是先不能lock().
使用defer_lock()可以不给mutex加锁,相当于初始化了一个没有加锁的mutex
使用方法:

class A
{
private:
	list<int>msgqueue;
	mutex mymutex1;

public:
	void MsgEnqueue()
	{

		for (int i = 0; i < 10000; ++i)
		{

			cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
			unique_lock<mutex>l(mymutex1,std::defer_lock);
			l.lock();//不需要自己unlock
			msgqueue.push_back(i);


		}
		return;
	}
	bool helper(int & command)
	{

		unique_lock<mutex>mylock (mymutex1);
		//chrono::microseconds d(2000);
		//this_thread::sleep_for(d);

		if (!msgqueue.empty())
		{
			command = msgqueue.front();
			msgqueue.pop_front();
			return true;
		}
		return false;
	}
	void MsgDequeue()
	{
		int command = 0;
		for (int i = 0; i < 10000; ++i)
		{
			bool result = helper(command);
			if (result)
			{
				cout << "helper执行,取出一个元素 " << command << endl;
			}
			else
			{
				cout << "MsgEnqueue()执行,但队列为空 " <<  i <<endl;
			}

		}
	}
};
int main()
{
	A a;
	thread t1(&A::MsgEnqueue, &a);
	thread t2(&A::MsgDequeue, &a);
	t1.join();
	t2.join();
	cout << endl;
}

在这里插入图片描述
也可以提前unlock解锁,处理一些非共享数据,如果想上锁了,可以再次lock().
比如:

		for (int i = 0; i < 10000; ++i)
		{

			cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
			unique_lock<mutex>l(mymutex1,std::defer_lock);
			l.lock();//不需要自己unlock

			l.unlock();
			//...
			//.处理非共享数据
			l.lock();
		
			msgqueue.push_back(i);


		}
		return;
	}

在这里插入图片描述

try_lock()

尝试给锁上锁,如果上锁失败,返回false,否则返回true
使用方法:

			cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
			unique_lock<mutex>l(mymutex1,std::defer_lock);
			if (l.try_lock() == true)
				msgqueue.push_back(i);
			else
				cout << "没拿到锁 " << i << endl;

release()

返回它管理的mutex对象指针,并释放所有权.
如果你release之前,已经加锁了,release之后你要负责unlock().
在这里插入图片描述
如果忘记unlock就会报错.

注意:unique_lock只能转移不能复制,比如:
在这里插入图片描述可以看到复制构造函数已经是被禁用了,但是你可以使用移动语义来进行转移:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44800780/article/details/104822530
今日推荐