在 《 C++11 并发指南三(std::mutex 详解) 》一文中我们主要介绍了 C++11 标准中的互斥量(Mutex),并简单介绍了一下两种锁类型。本节将详细介绍一下 C++11 标准的锁类型。
C++11 标准为我们提供了两种基本的锁类型,分别如下:
另外还提供了几个与锁类型相关的 Tag 类,分别如下:
struct adopt_lock_t {};
该类型的常量对象adopt_lock(adopt_lock 是一个常量对象,定义如下:
constexpr adopt_lock_t adopt_lock {};,// constexpr 是 C++11 中的新关键字)
通常作为参数传入给 unique_lock 或 lock_guard 的构造函数。
std::defer_lock_t,一个空的标记类,定义如下:
struct defer_lock_t {};
该类型的常量对象 defer_lock(defer_lock 是一个常量对象,定义如下:
constexpr defer_lock_t defer_lock {};,// constexpr 是 C++11 中的新关键字)
通常作为参数传入给 unique_lock 或 lock_guard 的构造函数。
std::try_to_lock_t,一个空的标记类,定义如下:
struct try_to_lock_t {};
该类型的常量对象 try_to_lock(try_to_lock 是一个常量对象,定义如下:
constexpr try_to_lock_t try_to_lock {};,// constexpr 是 C++11 中的新关键字)
通常作为参数传入给 unique_lock 或 lock_guard 的构造函数。后面我们会详细介绍以上三种 Tag 类型在配合 lock_gurad 与 unique_lock 使用时的区别。
std::lock_guard 介绍
std::lock_gurad 是 C++11 中定义的模板类。定义如下:
template <class Mutex> class lock_guard;
lock_guard 对象通常用于管理某个锁(Lock)对象,因此与 Mutex RAII 相关,方便线程对互斥量上锁,即在某个 lock_guard 对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而 lock_guard 的生命周期结束之后,它所管理的锁对象会被解锁(注:类似 shared_ptr 等智能指针管理动态分配的内存资源 )。
模板参数 Mutex 代表互斥量类型,例如 std::mutex 类型,它应该是一个基本的 BasicLockable 类型,标准库中定义几种基本的 BasicLockable 类型,分别 std::mutex, std::recursive_mutex, std::timed_mutex,std::recursive_timed_mutex (以上四种类型均已在上一篇博客中介绍)以及 std::unique_lock(本文后续会介绍 std::unique_lock)。(注:BasicLockable 类型的对象只需满足两种操作,lock 和 unlock,另外还有 Lockable 类型,在 BasicLockable 类型的基础上新增了 try_lock 操作,因此一个满足 Lockable 的对象应支持三种操作:lock,unlock 和 try_lock;最后还有一种 TimedLockable 对象,在 Lockable 类型的基础上又新增了 try_lock_for 和 try_lock_until 两种操作,因此一个满足 TimedLockable 的对象应支持五种操作:lock, unlock, try_lock, try_lock_for, try_lock_until)。
在 lock_guard 对象构造时,传入的 Mutex 对象(即它所管理的 Mutex 对象)会被当前线程锁住。在lock_guard 对象被析构时,它所管理的 Mutex 对象会自动解锁,由于不需要程序员手动调用 lock 和 unlock 对 Mutex 进行上锁和解锁操作,因此这也是最简单安全的上锁和解锁方式,尤其是在程序抛出异常后先前已被上锁的 Mutex 对象可以正确进行解锁操作,极大地简化了程序员编写与 Mutex 相关的异常处理代码。
值得注意的是,lock_guard 对象并不负责管理 Mutex 对象的生命周期,lock_guard 对象只是简化了 Mutex 对象的上锁和解锁操作,方便线程对互斥量上锁,即在某个 lock_guard 对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而 lock_guard 的生命周期结束之后,它所管理的锁对象会被解锁。
std::lock_guard 构造函数
lock_guard 构造函数如下表所示:
locking (1) |
explicit lock_guard (mutex_type& m); |
---|---|
adopting (2) |
lock_guard (mutex_type& m, adopt_lock_t tag); |
copy [deleted](3) |
lock_guard (const lock_guard&) = delete; |
locking 初始化
lock_guard 对象管理 Mutex 对象 m,并在构造时对 m 进行上锁(调用 m.lock())。
adopting初始化
lock_guard 对象管理 Mutex 对象 m,与 locking 初始化(1) 不同的是, Mutex 对象 m 已被当前线程锁住。
拷贝构造
lock_guard 对象的拷贝构造和移动构造(move construction)均被禁用,因此 lock_guard 对象不可被拷贝构造或移动构造。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/483688.html