微信号:hxzqlh

介绍:我在这里,只写三件事:读书笔记,技术总结,谈笑风生.

C++11从入门到放弃之 mutex

2016-06-27 23:48 黄学忠

在多线程的程序中,经常需要通过锁的机制来保证数据的一致性,C++11提供了下面四种语义的锁:

type function desc
mutex Lockable 普通的互斥锁,不能递归使用。
timed_mutex TimedLockable 带超时的互斥锁,不能递归使用。
recursive_mutex Lockable 递归互斥锁。
recursive_timed_mutex TimedLockable 带超时的递归互斥锁。

继承关系为:

BasicLockable <--- Lockable <--- TimedLockable
+lock              +try_lock     +try_lock_for
+unlock                          +try_lock_until

mutex

C++11 中最基本的互斥量,它不支持递归地上锁。

  • mutex 不允许拷贝构造,也不允许 move 赋值,最初产生的 mutex 对象是处于 unlocked 状态的。

  • lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:

    1. 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。

    2. 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。

    3. 如果当前互斥量被当前调用线程锁住,则会产生死锁。

  • unlock(), 解锁,释放对互斥量的所有权。

  • try_lock(),尝试锁住互斥量,和 lock() 相似,不同的是如果互斥量被其他线程占有,则当前线程也不会被阻塞,而是马上返回 false

recursive_mutex

  • 允许同一个线程对互斥量多次上锁,来获得对互斥量对象的多层所有权。

  • 释放互斥量时需要调用与该锁层次深度相同次数的 unlock()

time_mutex

  • 比 mutex 多了两个成员函数:try_lock_for()try_lock_until()

  • try_lock_for() 函数接受一个时间范围,表示在 一段时间范围之内 线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false

  • try_lock_until() 函数则接受一个时间点作为参数,在 指定时间点未到来之前 线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false

RAII

关于 mutex 的使用,建议使用 RAII(Resource Acquisition is Initialization)的方式,即在构造的时候 lock, 析构的时候 unlock, 不建议直接手工地进行 lock/unlock

C++11提供了 lock_guardunique_lock 两种简单而又安全的上锁和解锁方式,即使程序抛出了异常,先前已被上锁的 Mutex 对象也能正确进行解锁,极大地简化了与 Mutex 相关的异常处理代码。

template <class mutex> 
class lock_guard;

template <class mutex> 
class unique_lock;
  • 都是模版类,实例化参数 mutex 必须是个 BasicLockable 类型(即支持 lock 和 unlock)。

  • 都只负责在构造时对 mutex 加锁,析构时对 mutex 解锁,它们并不管理 mutex 本身的生命周期,因此,mutex 的生命周期应至少延伸至 lock_guard 和 unique_lock 析构之后。

lock_guard

  • 只有构造函数和析构函数。

unique_lock

  • 更灵活的初始化方式:

    1. default

    2. locking

    3. try_locking

    4. deferred

    5. adopting

    6. locking_for

    7. locking_until

    8. move


  • 除了基本的上锁/解锁操作,unique_lock 还支持修改、获取 mutex 的操作:

    1. move 移动赋值

    2. swap 与另一个 unique_lock 对象交换它们所管理的 Mutex 对象的所有权

    3. release 返回指向它所管理的 Mutex 对象的指针,并释放所有权

    4. owns_lock 返回当前 unique_lock 对象是否获得了锁

    5. operator bool() 与 owns_lock 功能相同 5. mutex 返回当前 unique_lock 对象所管理的 Mutex 对象的指针

参考

 
我为朝露谁苦多 更多文章 布冯的历史行程 《哭声》| 见神见鬼见人心 表驱动|码农的豹变 C++11从入门到放弃之condition_variable C++11从入门到放弃|atomic_flag
猜您喜欢 熬夜并不值得程序员炫耀 十分钟理解Gradle 《视频直播技术详解》之(四):编码和封装 资源的革命:互联网改变了商业的什么 恭祝中关村中心JSD1604系列班毕业班项目答辩圆满结束!