目录
unique_lock
1、正确的锁定顺序:在使用多个unique_lock对象对多个互斥量进行锁定时,应保持相同的锁定顺序,以避免死锁。
2、异常安全性:unique_lock提供了异常安全性,即在异常发生时,会自动释放互斥量。
因此,在使用unique_lock时,可以放心地使用RAII(资源获取即初始化)技术,避免忘记释放锁。
3、选择适当的锁定策略:unique_lock提供了两种锁定策略,即defer_lock和try_to_lock。
在选择锁定策略时,需要考虑是否希望避免阻塞线程,或者需要在特定条件下重新尝试锁定。
4、锁定粒度:在使用unique_lock时,应尽可能缩小锁定的粒度,以避免不必要的性能开销。只在必要时才对互斥量进行锁定。
5、避免无谓的锁定:unique_lock提供了lock和unlock成员函数,以手动控制锁定和解锁。在使用时,应避免无谓的锁定和解锁操作,以提高性能。
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;
}