lock_guard
比较简单,构造函数加锁,只在析构函数解锁,
而unique_lock
支持在析构函数调用之前,手动的调用unlock()
去释放锁,然后也可以手动加锁lock()
。
unique_lock 原型
template<typename _Mutex>
class unique_lock
{
public:
typedef _Mutex mutex_type;
unique_lock() noexcept
: _M_device(0), _M_owns(false)
{ }
explicit unique_lock(mutex_type& __m)
: _M_device(std::__addressof(__m)), _M_owns(false)
{
lock();
_M_owns = true;
}
unique_lock(mutex_type& __m, defer_lock_t) noexcept
: _M_device(std::__addressof(__m)), _M_owns(false)
{ }
unique_lock(mutex_type& __m, try_to_lock_t)
: _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
{ }
unique_lock(mutex_type& __m, adopt_lock_t) noexcept
: _M_device(std::__addressof(__m)), _M_owns(true)
{
// XXX calling thread owns mutex
}
~unique_lock()
{
if (_M_owns)
unlock();
}
unique_lock(const unique_lock&) = delete;
unique_lock& operator=(const unique_lock&) = delete;
unique_lock(unique_lock&& __u) noexcept
: _M_device(__u._M_device), _M_owns(__u._M_owns)
{
__u._M_device = 0;
__u._M_owns = false;
}
unique_lock& operator=(unique_lock&& __u) noexcept
{
if(_M_owns)
unlock();
unique_lock(std::move(__u)).swap(*this);
__u._M_device = 0;
__u._M_owns = false;
return *this;
}
//.... 这里着重将上面一些接口,后面可以自己打开去看
_M_owns : 是否拥有,使用lock()成功了
构造函数中的几个特殊鉴别参数:
- adopt_lock_t 用已经占用的锁进行实例化unique_lock,构造函数中不加锁,析构的时候会进行解锁;
{
std::mutex mtx;
//先枷锁
mtx.lock();
//这里的构造函数不会调用mtx的lock()
std::unique_lock<std::mutex> lck(mtx,std::adopt_lock);
//后面lck出作用域时会进行mtx.unlock()操作
}
- defer_lock_t 延迟拥有锁,构造中不加锁,如果使用途中不进行加锁,出栈区不释放;
{
std::mutex mtx;
//这里构造时不进行加锁
std::unique_lock<std::mutex> lck(mtx,std::defer_lock);
//这里展示延后加锁,既然加了锁析构会释放锁,如果没有这一步,析构也就不会进行释放锁
lck.lock()
//后面出作用域,会在lck对象的析构函数中进行解锁
}
- try_to_lock_t 构造函数中会去尝试加锁,不会阻塞,如果没有获取锁,析构函数中不会释放,通过owns_lock()判断;
std::mutex mtx;
//这里尝试加锁,调用mtx的 try_to_lock()
std::unique_lock<std::mutex> lck(mtx,std::try_to_lock);
//判断锁获取成功没有
if(lck.owns_lock())
{
//表示加锁成功
}
else
{
//表示没有获取到锁,加锁失败
}
底层的锁可进行转移
与 lock_guard
不同,虽然 unique_lock
也删除了左值类型的拷贝构造和赋值,但是新增了右值的拷贝构造函数与 赋值运算符重载函数,言下之意就是底层的管理的锁可以进行转移,转移给其他的unique_lock
对象,当前对象将会失去对锁的管控。
支持与时间相关的加锁接口
try_lock_until()
try_lock_for()
template<typename _Clock, typename _Duration>
unique_lock(mutex_type& __m,
const chrono::time_point<_Clock, _Duration>& __atime)
: _M_device(std::__addressof(__m)),
_M_owns(_M_device->try_lock_until(__atime))
{ }
template<typename _Rep, typename _Period>
unique_lock(mutex_type& __m,
const chrono::duration<_Rep, _Period>& __rtime)
: _M_device(std::__addressof(__m)),
_M_owns(_M_device->try_lock_for(__rtime))
{ }