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只能轉移不能複製,比如:
在這裏插入圖片描述可以看到複製構造函數已經是被禁用了,但是你可以使用移動語義來進行轉移:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章