C++多线程4-unique_lock详解

unique_lock和lock_guard都是可以自动解锁的类,但是lock_guard更加高效体现在永远在析构函数中解锁,而unique_lock更加灵活,但执行效率会比lock_guard低一些,它们都是有不同的应用场景。
unique_lock是通用互斥包装器,允许延迟锁定、尝试锁定、递归锁定、所有权转移和条件变量一同使用;它可以移动mutex的所有权,但不可复制;
1.unique_lock的行为,通过第二个参数控制:
a)std::adopt_lock
在unique_lock创建对象,有adopt_lock参数时,对象不能执行lock成员函数,因为它的使用场景是mutex已经加了锁。

//测试使用adopt_lock参数创建的对象调用lock函数
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

int main()
{
	mutex mutex_m;
	unique_lock<mutex> lock(mutex_m, std::adopt_lock);
	lock.lock();
	return 0;
}
//打印结果
terminate called after throwing an instance of 'std::system_error'
  what():  Resource deadlock avoided
Aborted (core dumped)

b)std::try_to_lock
在unique_lock创建对象,有try_to_lock参数时,对象会尝试去加锁,如果不成功,则会返回false,而不用继续等待。

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

class Test
{
public:
	Test():age_m(0)
	{
		cout << "Test构造函数" << endl;
	}

	~Test()
	{
		cout << "Test析构函数" << endl;
	}

	void set(const int age)
	{
		std::lock_guard<std::mutex> lockgd(mutex_m);
		std::this_thread::sleep_for(std::chrono::seconds(2));
		cout << "set ,thread id:" << std::this_thread::get_id()<< endl;
		age_m = age;
	}

	void get()
	{
		std::unique_lock<std::mutex> unilock(mutex_m, std::try_to_lock);
		if (unilock.owns_lock())
		{
			cout << "get lock, thread id:" << std::this_thread::get_id()<< endl;
			cout << "age:" << age_m << endl;
		}
		else
		{
			cout << "Cant get lock, thread id:" << std::this_thread::get_id()<< endl;
		}
	}

private:
	int age_m;
	static std::mutex mutex_m;
};

std::mutex Test::mutex_m;

int main()
{
	Test test;
	std::thread th[20];
//	std::thread first(&Test::set, &test, 20);
//	first.join();

	for (int i=0; i<20; i++)
	{
		if (i%20 == 0)
			th[i] = std::thread(&Test::set, &test, i);
		else
			th[i] = std::thread(&Test::get, &test);
	}

	for (int i=0; i<20; i++)
	{
		if (th[i].joinable())
		{
			th[i].join();
		}
	}
	return 0;
}
//打印结果
root@epc:/home/share/eclipse_workspace/exercise/src#  ./exercise
Test构造函数
get lock, thread id:139643157436160
age:0
Cant get lock, thread id:139643149043456
Cant get lock, thread id:139643140650752
Cant get lock, thread id:139643165828864
get lock, thread id:139643132258048
age:0
Cant get lock, thread id:139643123865344
Cant get lock, thread id:139643115472640
get lock, thread id:139643174221568
age:0
Cant get lock, thread id:139643107079936
get lock, thread id:139643098687232
age:0
get lock, thread id:139643090294528
age:0
get lock, thread id:139643081901824
age:0
Cant get lock, thread id:139643182614272
get lock, thread id:139643073509120
age:0
get lock, thread id:139643065116416
age:0
get lock, thread id:139643056723712
age:0
get lock, thread id:139643048331008
age:0
get lock, thread id:139643191006976
age:0
get lock, thread id:139643199399680
age:0
set ,thread id:139643207792384
Test析构函数

c)std::defer_lock
在unique_lock创建对象,有defer_lock参数时,需要调用成员函数lock进行加锁;

class Test
{
public:
	Test():age_m(0)
	{
		cout << "Test构造函数" << endl;
	}

	~Test()
	{
		cout << "Test析构函数" << endl;
	}

	void set(const int age)
	{
		std::lock_guard<std::mutex> lockgd(mutex_m);
//		std::this_thread::sleep_for(std::chrono::seconds(1));
		cout << "set age= " << age << " ,thread id:" << std::this_thread::get_id()<< endl;
		age_m = age;
	}

	void get()
	{
		std::unique_lock<std::mutex> unilock(mutex_m, std::defer_lock);
		if (unilock.try_lock())
		{
			cout << "get age=" << age_m <<  ", get lock, thread id:" << std::this_thread::get_id()<< endl;
		}
		else
		{
			cout << "Cant get lock, thread id:" << std::this_thread::get_id()<< endl;
		}
	}

private:
	int age_m;
	static std::mutex mutex_m;
};

std::mutex Test::mutex_m;

2.unique_lock成员函数:
a)lock
在unique_lock创建对象,有defer_lock参数时,需要调用成员函数lock进行加锁;
b)unlock
可以利用unlock成员函数来控制加锁代码的粒度;
c)try_lock
在unique_lock创建对象,有defer_lock参数时,可以利用成员函数try_lock尝试加锁,成功则返回true,不成功则返回false;
d)release
执行完release后,将mutex的所有权释放,并返回mutex的对象指针;
举例:

std::mutex* mutex_p = unilock.release();
if (mutex_p != nullptr) mutex_p->unlock();

3.unique的所有权传递
unique_lock不支持拷贝和赋值,
举例:

std::unique_lock<std::mutex> templock(mutex_m, std::defer_lock);
std::unique_lock<std::mutex> unilock(move(templock));
发布了32 篇原创文章 · 获赞 3 · 访问量 1410

猜你喜欢

转载自blog.csdn.net/m0_37582216/article/details/102502714