一、unique_lock 取代 lock_guard
- unique_lock是个类模板,比lock_guard 相对更灵活
二、 unique_lock**的第二个参数
- std::adopt_lock: 是个结构体对象,起一个标记作用:表示这个互斥量已经lock(),不需要在std::lock_guard构造函数里面对对象进行再次lock()了(用这个adopt_lock前提是你自己需要先去lock)
mutex1.lock(); std::unique_lock<std::mutex> guard1(mutex1, std::adopt_lock);
- std::try_to_lock : 会尝试用mutex的lock()去锁这个mutex,但如果没有锁成功,我也会立即返回并不会阻塞在那里(用这个try_to_lock前提是你自己不能先去lock)
std::unique_lock<std::mutex> guard1(mutex1, std::try_to_lock); if (guard1.owns_lock()) //判断是否拿到了锁,拿到了锁,拿到了锁才能操作共享数据 { cout << "插入一个元素 : " << i << endl; m_list.push_back(i); } else { cout << "我还没拿到锁呢" << endl; }
- std::defer_lock: 初始化了一个没加锁的mutex(用这个try_to_lock前提是你自己不能先去lock)
三、unique_lock的成员函数
- lock()函数 : 加锁 不需要自己unlock()
unique_lock<mutex> unique(mutex1, std::defer_lock); //没有加锁的mutex unique.lock(); //不用自己unlock() m_list.push_back(i);
- unlock()函数 :解锁
unique_lock<mutex> unique(mutex1, std::defer_lock); //没有加锁的mutex unique.lock(); //不用自己unlock() //.....因为有一些非共享代码需要处理 所以临时需要先解锁 unique.unlock(); //又处理一些共享代码 可以又临时把锁加上 unique.lock(); m_list.push_back(i);
- try_lock()函数 :尝试给互斥量加锁,如果拿不到锁,则返回false ,如果拿到了就返回true
unique_lock<mutex> unique(mutex1, std::defer_lock); //没有加锁的mutex if (unique.try_lock() == true) { m_list.push_back(i); } else { cout << "我还没拿到锁呢" << endl; }
- release()函数 : 返回它所管理的原始mutex对象指针,并释放所有权(也就是说,这个unique_lock和mutex不再有关系);如果原来mutex对象处于加锁状态,你有责任接管过来并负责解锁
unique_lock<mutex> unique(mutex1); std::mutex *ptr = unique.release(); //现在有责任自己解锁mutex m_list.push_back(i); ptr->unlock(); //自己负责 unlock();
锁的粒度:锁住代码的多少,一般用粗细来描述,粒度越细,代码执行效率越高,相反越低
四、unique_lock所有权的传递
std::unique_lock<std::mutex> unique(mutex1); //unique拥有mutex1的所有权
//unique可以把自己对mutex(mutex1)的所有权转移给其他unique_lock对象,可以转移但是不能复制
unique_lock<mutex> unique(mutex1);
unique_lock<mutex> unique1(unique); //错误写法,非法,不能复制
unique_lock<mutex> unique1(std::move(unique)); //正确写法,合法 //此时 unique 为空
也可以这样传递:
std::unique_lock<std::mutex> GetUnique_Lock()
{
std::unique_lock<std::mutex> unique(mutex1);
return unique; //返回局部对象
}
unique_lock<mutex> unique1 = GetUnique_Lock();