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

    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);

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

  • 相关阅读:
    回调函数: 一定要在函数名前加上 CALLBACK,否则有可能引起内存崩溃!
    win32-api: 让 static 控件中的水平横行,垂直居中。
    Win32-API: 终于能正常的捕获焦点事件: WM_COMMAND、BN_SETFOCUS、EN_SETFOCUS
    FindExecutable:查找与一个指定文件关联在一起的程序的文件名
    ImageMagick: win7 | win8 & uac (用户帐户控制) 注册表的一些事
    ImageMagick: 6.8.3 升级到 6.8.9 遇到的问题
    ImageMagick: DrawImage(Image*,DrawInfo*) 绘制填充图片时卡住的原因分析
    真的无语, 今天遇到一个奇葩的事情: http 会话劫持
    高DPI下界面错乱的解决方法和原理
    关于 HDC 的释放
  • 原文地址:https://www.cnblogs.com/defe-learn/p/7008277.html
Copyright © 2011-2022 走看看