C++多线程编程之unqiue_lock和lock_guard

参考www.cplusplus.com

std::adopt_lock_t

struct adopt_lock_t {};

该类是一个空类,用于定义adopt_lock常量对象,adopt_lock可传递给unique_locklock_guard的构造函数,使得它们在构造对象时不会对mutex对象上锁,而是假定mutex对象已经被当前线程上锁,并标记自身状态为已拥有锁。
adopt_lock常量位于std命名空间中:

constexpr adopt_lock_t adopt_lock {};

std::defer_lock_t

struct defer_lock_t {};

defer_lock_t也是一个空类,用于定义常量defer_lock。可以将它传递给unique_lock的构造函数,使其在构造对象时不会自动地锁住mutex对象,并将unique_lock初始化为不拥有锁。
defer_lock常量位于std命名空间中:

constexpr defer_lock_t defer_lock {};

std::try_to_lock_t

struct try_to_lock_t {};

try_to_lock_t创建的常量对象try_to_lock可传递给unique_lock的构造函数,构造函数会调用try_lock函数尝试锁住mutex对象,若成功上锁,则标记unique_lock对象的状态为拥有锁;否则,标记该对象的状态为没有拥有锁。

constexpr try_to_lock_t try_to_lock {};

std::lock_guard

template <class Mutex> class lock_guard;

lock_guard类用于管理锁类型的对象,在构造函数中会上锁,直到调用析构函数时才会解锁。

lock_guard构造函数

explicit lock_guard (mutex_type& m);
lock_guard (mutex_type& m, adopt_lock_t tag);
lock_guard (const lock_guard&) = delete;
  • 第一种构造函数会调用m.lock()函数锁住m,需要显式调用该构造函数;若m已经上锁,则会抛出异常
  • 第二种构造函数不会上锁,而是认为当前线程已经对m上锁了,仅仅是领养m。因此,线程必须对m上锁。
  • lock_guard对象不可拷贝和移动。

lock_guard析构函数

~lock_guard();

该析构函数会调用unlock函数解锁,并销毁lock_guard对象,但不会销毁mutex对象。

#include <iostream>
#include <mutex>
std::mutex mt1, mt2;
int main(int argc, char** argv)
{
	mt1.lock();//mt1上锁
	{
		std::lock_guard<std::mutex> lck_guard1(mt1, std::adopt_lock_t{});//lck_guard1不会对mt1上锁,而是adopt该锁,在此之前,mt1应该已上锁
	}//lck_guard1会被销毁,调用析构函数会解锁mt1
	{
		std::lock_guard<std::mutex> lck_guard2(mt2, std::adopt_lock_t{});
	}//lck_guard2会被销毁,并调用析构函数解锁mt2,由于mt2并没有上锁,因此会抛出system_error异常,提示“unlock of unowned mutex”
	return 0;
}

std::unique_lock

template <class Mutex> class unique_lock;

unique_lock有两个私有数据成员,指针和状态,指针指向管理的锁类型的对象,状态标记则标记unique_lock对象是否拥有锁。
lock_guard一样,unique_lock也用于管理锁类型的对象,但更加灵活,可以手动的上锁和解锁、释放锁(放弃对锁对象的管理权)和移交锁等操作。

构造函数

  1. 默认构造函数
unique_lock() noexcept;

默认构造函数,没有可管理的锁类型对象。

  1. locking initialization
explicit unique_lock (mutex_type& m);

管理锁类型对象m,并调用m.lock()对其进行上锁,若已处于上锁状态,则会阻塞当前线程。

  1. try-locking initialization
unique_lock (mutex_type& m, try_to_lock_t tag);

管理锁类型对象m,并调用m.try_lock()尝试上锁。

  1. deferred initialization
unique_lock (mutex_type& m, defer_lock_t tag) noexcept;

管理锁类型对象m,但不会对其上锁。m不该被构造线程锁住。

  1. adopting initialization
unique_lock (mutex_type& m, adopt_lock_t tag);

m对象被构造线程锁住,unique_lock对象获得锁的所有权。

  1. locking for duration
template <class Rep, class Period>
unique_lock (mutex_type& m, const chrono::duration<Rep,Period>& rel_time);

通过调用m.try_lock_for(rel_time)函数,尝试在rel_time时间内锁住m

  1. locking until time point
template <class Clock, class Duration>
unique_lock (mutex_type& m, const chrono::time_point<Clock,Duration>& abs_time);

通过调用m.try_lock_until(abs_time),尝试在abs_time之前锁住m

  1. copy construction [deleted]
unique_lock (const unique_lock&) = delete;

拷贝构造函数不可用。

  1. move construction
unique_lock (unique_lock&& x);

移动构造函数,当前对象会获得由x管理的锁对象,包括锁的状态。

析构函数

~unique_lock();

若对象现在拥有锁,先解锁,然后再销毁该对象。但不会销毁锁类型对象。

成员函数

unique_lock::owns_lock

若管理的锁类型对象被该对象锁住或adopted,并且在调用该函数时还未解锁或释放锁类型对象,则返回true。其他情况返回false
该函数与unique_lock::operator bool作用一样。

unique_lock::lock

void lock();

调用管理的锁类型对象的lock函数进行上锁,若该锁类型对象已经被其他线程锁住,则当前线程阻塞,直到可以拥有锁时。
当函数返回时,unique_lock对象就获得了锁。

unique_lock::try_lock

bool try_lock();

该函数会调用锁类型对象的try_lock成员函数。若该对象没有管理锁类型对象或锁类型对象已经被上锁,则函数被抛出system_error异常。
成功获得锁则返回true,否则返回false

unique_lock::try_lock_for

template <class Rep, class Period>
  bool try_lock_for (const chrono::duration<Rep,Period>& rel_time);

unique_lock::try_lock_until

template <class Clock, class Duration>
  bool try_lock_until (const chrono::time_point<Clock,Duration>& abs_time);

unique_lock::unlock

void unlock();

若没有管理锁,或不拥有锁,则抛出异常;否则调用锁的unlock()函数。

unique_lock::mutex

mutex_type* mutex() const noexcept;

返回管理的锁类型对象的指针。

unique_lock::operator=

移动赋值运算符:

unique_lock& operator= (unique_lock&& x) noexcept;

x管理的锁类型对象替换当前管理的锁类型对象,包括锁的状态。
若当前对象管理的锁类型对象已经上锁,则先解锁再替换。
拷贝赋值运算符:

unique_lock& operator= (const unique_lock&) = delete;

unique_lock::operator bool

explicit operator bool() const noexcept;

若管理的锁类型对象被当前对象上锁或adopted,则返回true
owns_lock函数功能一样。

unique_lock::release

mutex_type* release() noexcept;

释放对管理的锁类型对象的所有权,并返回锁类型对象的指针。
调用该函数后,当前对象便处于没有管理任何锁类型对象的状态(与使用默认构造函数构造的对象的状态一样)。
该函数不会对释放的锁类型对象进行上锁或解锁操作。

unique_lock::swap

void swap (unique_lock& x) noexcept;

交换当前对象与x的内容,包括管理的锁类型对象和当前的拥有状态(当前对象对锁类型对象上锁了或adopted,就是拥有该锁的状态,否则就是不拥有该锁)。

友元函数

std::swap

template <class Mutex>
void swap (unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;

交换xy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值