unique_lock是一个类模板,可以完全取代lock_guard;
它的灵活性比lock_guard高很多,但是相对的,他的效率,内存的占用要高一些。
用法同lock_guard():
unique_lock< mutex > myUnique(mutex);
用法:
mutex mutex1;
mutex1.lock(); //adopt_lock的前提是线程必须先lock(),否则会报错
std::unique_lock<std::mutex> myUnique(mutex1, adopt_lock); //用法同lock_guard的adopt_lock参数
mutex mutex1;
//mutex1.lock(); //try_to_lock参数的前提是不可以提前lock()
std::unique_lock<std::mutex> myUnique(mutex1, try_to_lock); //unique_lock的try_to_lock参数用法
if(myUnique.owns_locks()){
//拿到了锁
}
else{
//未拿到锁
}
用法:
mutex mutex1;
//mutex1.lock(); //try_to_lock参数的前提是不可以提前lock()
std::unique_lock<std::mutex> myUnique(mutex1,defer_lock); //创建一个没有加锁的mutex1
//后续可以调用unique_lock的一些方法
myUnique.lock();//加锁,不需要unlock(),会析构的时候自动unlock();
unique_lock的lock()方法,手动加锁,自动解锁(析构的时候自动调用unlock()),unique_lock引入lock方法的意义是增加灵活性,不是一定要在定义unique_lock的时候自动调用lock()(构造函数默认调用lock())。
mutex mutex1;
//mutex1.lock(); //try_to_lock参数的前提是不可以提前lock()
std::unique_lock<std::mutex> myUnique(mutex1,defer_lock); //创建一个没有加锁的mutex1
myUnique.lock();//加锁,不需要unlock(),会析构的时候自动unlock();
unlock():解锁,默认调用了lock()就会在析构的时候自动调用unlock;
引入unlock()的目的也是为了增加灵活性,有可能我们在析构之前,需要对互斥量进行访问,这时候就需要我们手动unlock,处理完毕后,再lock。
lock住的代码段越少,执行越快,整个程序运行效率高,有人也把锁头锁住的代码多少称为锁的粒度,粒度一般用粗细来描述;
a)锁住的代码少,粒度细,执行效率高
b)锁住的代码多,粒度粗,执行效率低
要尽量选择适合粒度的代码进行保护,粒度太细可能漏掉共享数据的保护,粒度太粗,影响效率。
mutex mutex1;
std::unique_lock<std::mutex> myUnique(mutex1, defer_lock);//创建一个没有加锁的mutex1
myUnique.lock(); //手动lock
//处理一些共享代码
myUnique.unlock(); //手动unlock
//处理一些非共享代码
myUnique.lock(); //处理完毕,再手动lock
//处理一些共享代码
try_lock尝试给互斥量加锁,返回true or false,与owns_locks()比较类似,这个函数是不阻塞的。
mutex mutex1;
std::unique_lock<std::mutex> myUnique(mutex1, defer_lock);//创建一个没有加锁的mutex1
if(myUnique.try_lock()){
//拿到了锁
}
else{
//未拿到锁
}
mutex*
来接收。mutex mutex1;
std::unique_lock<std::mutex> myUnique(mutex1, defer_lock);//创建一个没有加锁的mutex1
std::mutex *ptx = myUnique.release();//ptx指向现在的mutex1,需要自己手动unlock
ptx->unlock();
std::unique_lock
std::unique_lock<std::mutex> myUnique(mutex1);
std::unique_lock<std::mutex> myUnique2(myUnique); //错误,复制mutex对象是非法的
std::unique_lock<std::mutex> myUnique2(mutex1); //正确,再绑定一个mutex对象是合法的
下面是所有权的传递方法:
std::unique_lock<std::mutex> myUnique(mutex1);
std::unique_lock<std::mutex> myUnique2(std::move(myUnique));
从函数中返回一个局部的unique_lock对象是可以的
返回局部对象会导致系统生成一个临时的unique_lock对象,并调用unique_lock的移动构造函数;
std::unique_lock<std::mutex>rtn_unique_lock()
{
std::unique_lock < std::mutex > tmpguard(mutex1);
return tmpguard;//从函数返回一个局部的unique_lock()对象是可以的,
//返回这种局部对象tmpguard会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数
}
// ......
std::unique_lock<std::mutex>myUnique2 = rtn_unique_lock();//mutex1的控制权转移给myUnique2