zoukankan      html  css  js  c++  java
  • C++标准库之mutex

    互斥锁有可重入、不可重入之分。C++标准库中用mutex表示不可重入的互斥锁,用recursive_mutex表示可重入的互斥锁。为这两个类增加根据时间来阻塞线程的能力,就又有了两个新的互斥锁:timed_mutex(不可重入的锁)、recursive_timed_mutex(可重入的锁)。

    互斥锁单独使用时主要是为了使对共享资源的互斥使用,即同时只能有一个线程使用,以防止同时使用可能造成的数据问题。

    C++标准库的所有mutex都是不可拷贝的,也不可移动。

    mutex基本操作

    上锁 lock 如果mutex未上锁,则将其上锁。否则如果已经其它线程lock,则阻塞当前线程。

    上锁 try_lock 如果mutex未上锁,则将其上锁。否则返回false,并不阻塞当前线程。

    解锁 unlock  如果mutex被当前线程锁住,则将其解锁。否则,是未定义的行为。

    timed_mutex在mutex的基础上增加了以下两个操作

    try_lock_for(duration) 如果timed_mutex未上锁,则将其上锁,否则阻塞当前线程,但最长只阻塞duration表示的时间段。

    try_lock_until(time_point) 如果timed_mutex未上锁,则将其上锁,否则阻塞当前线程,但最长只会阻塞到time_point表示的时间点就不再阻塞。

    try_lock_for/until可以检测到死锁的出现,这是目前想到的一种用途。

    if(!try_lock_for(chrono::hours(1)))
    {
      throw "出现死锁!";  
    }

    可重入的锁 recursive_mutex、recursive_timed_mutex与对应的mutex、timed_mutex操作一致。不同点在于,不可重入的锁在lock或try_lock一个已经被当前线程lock的锁时会导致死锁,而可重入的锁不会。

    辅助类

    template<class Mutex> class lock_guard;

    lock_guard用于脱离lock_guard对象生存期后自动对互斥锁进行解锁操作。

    explicit lock_guard(mutex_type &m);对象创建时执行 m.lock(),对象销毁时执行 m.unlock()

    explicit lock_guard(mutex_type &m,adpot_lock_t tag);对象创建不执行lock,对象销毁时执行 m.unlock()。所以m应该是一个已经被当前线程lock的互斥锁。

    template<class Mutex> class unique_lock;

    unique_lock()noexcept;不管理任何锁。

    explicit unique_lock(mutex_type &m);对象创建时执行 m.lock()。

    unique_lock(mutex_type &m,try_to_lock_t tag);对象创建时执行 m.try_lock()。

    unique_lock(mutex_type &m,defer_lock_t tag);对象创建时不进行上锁操作,m要满足没有被当前线程锁住的条件。

    unique_lock(mutex_type &m,adopt_lock_t tag);对象创建时不进行上锁操作,m要满足已经被当前线程锁住的条件。

    unique_lock(mutex_type &m,const duration & real_time);对象创建时执行 m.try_lock_for(real_time)。

    unique_lock(mutex_type &m,const time_point & abs_time);对象创建时执行 m.try_lock_until(abs_time)。 

    unique_lock(unique_lock &&);移动构造

    操作:unique_lock具备它所管理的锁的所有操作 lock、unlock、try_lock、try_lock_for、try_lock_until。

    mutex_type *release(); 不再管理互斥锁。

    void swap(unique_lock &);交换管理的互斥锁。

    bool owns_lock() 用于探测unique_lock是否管理着一个互斥锁且其处于上锁状态。bool operate bool() 与owns_lock等同。

    mutex_type * mutex();用于返回管理的互斥锁的指针,但仍对其进行管理。

    在unique_lock销毁的时候,owns_lock为真才会执行unlock。

    总的来说,lock_guard在时空间效率上比较高,但功能单一。unique_lock功能多,使用灵活,但时空间效率不如lock_guard。如果使用了辅助类来管理互斥锁,就不要直接操作锁了,否则容易引发混乱,产生BUG。

    辅助函数

    template <class Mutex1, class Mutex2, class... Mutexes>
    int try_lock (Mutex1& a, Mutex2& b, Mutexes&... cde);

    根据参数顺序对多个锁进行上锁,如果成功锁住所有锁,返回-1,返回值大于0表示失败的锁的位置号。

    template <class Mutex1, class Mutex2, class... Mutexes>
    void lock (Mutex1& a, Mutex2& b, Mutexes&... cde);

    对多个锁进行上锁,该函数是阻塞的。另,它保证发生异常的情况下已经上锁的锁会被解锁。

  • 相关阅读:
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
    手动部署 Ceph Mimic 三节点
    Ceph 分布式存储架构解析与工作原理
    OpenStack 的单元测试
    OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)
    我非要捅穿这 Neutron(四)Open vSwitch in Neutron
    手动部署 OpenStack Rocky 双节点
    OpenStack Blazar 架构解析与功能实践
    基于 Open vSwitch 的 OpenFlow 实践
    OpenFlow/SDN 的缘起与发展
  • 原文地址:https://www.cnblogs.com/vsuu/p/4170520.html
Copyright © 2011-2022 走看看