C++多线程学习(七、unique_lock)

目录

unique_lock

unique_lock加锁过程

unique_lock中使用adopt_lock

unique_lock中使用defer_lock

unique_lock中使用try_to_lock


unique_lock

1、正确的锁定顺序:在使用多个unique_lock对象对多个互斥量进行锁定时,应保持相同的锁定顺序,以避免死锁。

2、异常安全性:unique_lock提供了异常安全性,即在异常发生时,会自动释放互斥量。

        因此,在使用unique_lock时,可以放心地使用RAII(资源获取即初始化)技术,避免忘记释放锁。

3、选择适当的锁定策略:unique_lock提供了两种锁定策略,即defer_locktry_to_lock

        在选择锁定策略时,需要考虑是否希望避免阻塞线程,或者需要在特定条件下重新尝试锁定。

4、锁定粒度:在使用unique_lock时,应尽可能缩小锁定的粒度,以避免不必要的性能开销。只在必要时才对互斥量进行锁定。

5、避免无谓的锁定:unique_lock提供了lockunlock成员函数,以手动控制锁定和解锁。在使用时,应避免无谓的锁定和解锁操作,以提高性能。

6、选择适当的互斥量:在选择使用unique_lock时,需要根据具体需求选择适当的互斥量类型。

        比如,如果需要支持递归锁定,则可以选择std::recursive_mutex;如果需要支持多个线程同时读取共享数据,可以选择std::shared_mutex等。

unique_lock加锁过程

#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
class Things
{
public:
	void goToilet()
	{
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex> unique(mtx);//一样是在构造函数和析构函数中进行加锁和解锁的过程
			cout << "上厕所" << endl;
			num.push_back(i);
		}
	}
	void goBath()
	{
		for (int i = 0; i < 10000; i++)
		{
			if (!num.empty())
			{
				unique_lock<mutex> unique(mtx);
				cout << "洗澡" << endl;
				num.pop_back();
			}
			else
			{
				cout << "干其他事情" << endl;
			}
		}
	}
protected:
	list<int> num;
	mutex mtx;
};
int main()
{
	Things DoSomeThing;
	thread t1(&Things::goToilet, &DoSomeThing);
	thread t2(&Things::goBath, &DoSomeThing);
	t1.join();
	t2.join();

	return 0;
}

unique_lock中使用adopt_lock

使用adopt_lock之前需要先进行lock,否则会执行abort终止程序。

#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
class Things
{
public:
	void goToilet()
	{
		for (int i = 0; i < 10000; i++)
		{
			mtx.lock();//使用adopt_lock需要先进行上锁
			unique_lock<mutex> unique(mtx,adopt_lock);
			cout << "上厕所" << endl;
			num.push_back(i);
		}
	}
	void goBath()
	{
		for (int i = 0; i < 10000; i++)
		{
			if (!num.empty())
			{
				mtx.lock();//使用adopt_lock需要先进行上锁
				unique_lock<mutex> unique(mtx, adopt_lock);
				cout << "洗澡" << endl;
				num.pop_back();
			}
			else
			{
				cout << "干其他事情" << endl;
			}
		}
	}
protected:
	list<int> num;
	mutex mtx;
};
int main()
{
	Things DoSomeThing;
	thread t1(&Things::goToilet, &DoSomeThing);
	thread t2(&Things::goBath, &DoSomeThing);
	t1.join();
	t2.join();

	return 0;
}

unique_lock中使用defer_lock

使用defer_lock,是给你安装了一个没有上锁的锁,需要自己去手动上锁。

能够更好的在局部去进行微操。

#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
class Things
{
public:
	void goToilet()
	{
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex> unique(mtx,defer_lock);//没有上锁的锁
			unique.lock();
			cout << "上厕所" << endl;
			unique.unlock();
			num.push_back(i);
			unique.lock();
		}
	}
	void goBath()
	{
		for (int i = 0; i < 10000; i++)
		{
			if (!num.empty())
			{
				unique_lock<mutex> unique(mtx);
				cout << "洗澡" << endl;
				num.pop_back();
			}
			else
			{
				cout << "干其他事情" << endl;
			}
		}
	}
protected:
	list<int> num;
	mutex mtx;
};
int main()
{
	Things DoSomeThing;
	thread t1(&Things::goToilet, &DoSomeThing);
	thread t2(&Things::goBath, &DoSomeThing);
	t1.join();
	t2.join();

	return 0;
}

unique_lock中使用try_to_lock

#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
class Things
{
public:
	void goToilet()
	{
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex> unique(mtx,try_to_lock);//try_to_lock测试去锁
			if (unique.owns_lock())//判断能不能成功的获取到锁
			{
				cout << "上厕所" << endl;
				num.push_back(i);
			}
		}
	}
	void goBath()
	{
		for (int i = 0; i < 10000; i++)
		{
			if (!num.empty())
			{
				unique_lock<mutex> unique(mtx);
				cout << "洗澡" << endl;
				num.pop_back();
			}
			else
			{
				cout << "干其他事情" << endl;
			}
		}
	}
protected:
	list<int> num;
	mutex mtx;
};
int main()
{
	Things DoSomeThing;
	thread t1(&Things::goToilet, &DoSomeThing);
	thread t2(&Things::goBath, &DoSomeThing);
	t1.join();
	t2.join();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/q244645787/article/details/131581344