unique_lock详解
-
unique_lock取代lock_guard
unique_lock
是一个类模板,其将一个互斥量与自身绑定,可以完全取代lock_guard
unique_lock<mutex> myguard(mymutex)
等价于lock_guard<mutex> myguard(mymutex)
相比于lock_guard
,unique_lock
更加灵活,但在效率上差一点,内存占用上多一点。 -
unique_lock的第二个参数
adopt_lock
示例:unique_lock<mutex> myguard(mymutex, adopt_lock)
作用:表明互斥量mymutex
已经被lock()
上了,不会在unique_lock
的构造函数中调用mymutex.lock()
,因此在使用这个参数前必须将互斥量上锁。
try_to_lock
示例:unique_lock<mutex> myguard(mymutex, try_to_lock)
作用:尝试去锁上互斥量mymutex
,如果没有锁上也不会在此处等待,而是立刻返回,因此在使用前不能将互斥量上锁。void inMsgRecvQueue() { for (int i = 0; i < 10; ++i) { cout << "inMessageQueue执行,插入一个元素" << i << endl; unique_lock<mutex> myguard(mymutex, try_to_lock); //使用成员函数owns_lock()来 判断是否上锁成功 if (myguard.owns_lock()){ msgRecvQueue.push_back(i); } else { cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl; } } }
defer_lock
示例:unique_lock<mutex> myguard(mymutex, defer_lock)
作用:初始化了一个没有加锁的互斥量,可以配合其成员函数灵活使用,因此在使用前不能将互斥量上锁。void inMsgRecvQueue() { for (int i = 0; i < 10; ++i) { cout << "inMessageQueue执行,插入一个元素" << i << endl; unique_lock<mutex> myguard(mymutex1, defer_lock); myguard.lock(); //开始处理共享数据1 myguard.unlock(); myguard.lock(); //开始处理共享数据2 if (myguard1.owns_lock()){ msgRecvQueue.push_back(i); } else { cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl; } } }
注意:如果在最后面给互斥量解锁了,在函数结束时,
myguard
调用析构函数将不会执行mymutex.unlock()
-
unique_lock的成员函数
lock():给其绑定的互斥量上锁
unlock():给其绑定的互斥量解锁
try_lock():尝试给互斥量上锁,如果成功,返回True,否则返回False,此函数不会造成阻塞void inMsgRecvQueue() { for (int i = 0; i < 10; ++i) { cout << "inMessageQueue执行,插入一个元素" << i << endl; unique_lock<mutex> myguard(mymutex, defer_lock); if (myguard.try_lock()){ msgRecvQueue.push_back(i); } else { cout << "执行inMsgRecvQueue(),没拿到锁,只能干点别的" << endl; } } }
release():
返回它所绑定的mutex
对象指针,并释放所有权,此后mymutex
与myguard
不再有关
如果原mutex
处于加锁状态,有责任在处理完后进行mutex.unlock()
操作void inMsgRecvQueue() { for (int i = 0; i < 10; ++i) { cout << "inMessageQueue执行,插入一个元素" << i << endl; unique_lock<mutex> myguard(mymutex); mutex* p = myguard.release(); msgRecvQueue.push_back(i); p->unlock(); } }
-
unique_lock所有权的传递
unique_lock<mutex> myguard(mymutex, defer_lock)
当一个unique_lock
与一个mutex
绑定后,unique_lock
就拥有了mutex
的所有权
所有权可以转移move()
但不能复制,类似与智能指针unique_ptr
void inMsgRecvQueue() { for (int i = 0; i < 10; ++i) { cout << "inMessageQueue执行,插入一个元素" << i << endl; unique_lock<mutex> myguard1(mymutex); unique_lock<mutex> myguard2(move(myguard1)); msgRecvQueue.push_back(i); } }
转移后
myguard2
继承了myguard1
所绑定的mutex
,myguard1
什么都不绑定。