unique_lock可以提供自动加锁、解锁功能,比lock_guard更加灵活,但比较耗时。
unique_lock的常规用法与lock_guard相似,代码如下:
bool outMsgProc(int &num)
{
unique_lock<mutex> guard(myMutex1);
if (!myList.empty())
{
num = myList.front();
myList.pop_front();
return true;
}
return false;
}
但是,unique_lock的构造函数可以有第二参数,可选值为:adopt_lock_t、defer_lock_t或try_to_lock_t,本文会分别介绍。
1.adopt_lock_t
adopt_lock_t表示互相量已经被锁定,创建unique_lock对象时,不再重复锁定。
bool outMsgProc(int &num)
{
myMutex1.lock(); //锁定myMutex1
unique_lock<mutex> guard(myMutex1, adopt_lock); //不再重复锁定myMutex1
if (!myList.empty())
{
num = myList.front();
myList.pop_front();
return true;
}
return false;
}
2.defer_lock_t
不为互斥量加锁,unique_lock()之前也没有加锁。初始化unique_lock对象之后,可以调用成员函数lock()和unlock()来加锁和解锁,体现了一定的灵活性。
void InMsg()
{
for (int i = 0; i < 10000; i++)
{
cout << "插入元素: " << i << endl;
unique_lock<mutex> guard(myMutex1, defer_lock); //初始化guard时,没有对互斥量myMutex1加锁
guard.lock(); //加锁
myList.push_back(i);
}
}
当然,也调用成员函数try_lock(),它不阻塞代码,当加锁成功时返回true,失败时返回false。
void InMsg()
{
for (int i = 0; i < 10000; i++)
{
cout << "插入元素: " << i << endl;
unique_lock<mutex> guard(myMutex1, defer_lock); //初始化guard时,没有对互斥量myMutex1加锁
if (guard.try_lock())
{
myList.push_back(i);
}
else
{
//没有拿到锁时,执行的代码
}
}
}
成员函数release(),返回它管理的mutex对象指针,并释放所有权(即互斥量mutex和unique_lock对象不再关联。此后互斥量的加锁和解锁由自己负责)。
void InMsg()
{
for (int i = 0; i < 10000; i++)
{
cout << "插入元素: " << i << endl;
unique_lock<mutex> guard(myMutex1); //构造函数中,对互斥量myMutex1加锁
mutex* ptr = guard.release(); //解除guard和myMutex1的关系
myList.push_back(i);
ptr->unlock(); //互斥量自己负责unlock()
}
}