2021-4-9 C++ 11之mutex

问题来源:leetcode简单题1114按序打印
首先针对这个问题给出一种做法:(看底下题解说的是这样写是不正确的,但是可以ac)

class Foo {
private:
mutex mu1;
mutex mu2;
public:
    Foo() {
        mu1.lock();
        mu2.lock();
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        mu1.unlock();	//给second提供解锁操作
    }

    void second(function<void()> printSecond) {
        mu1.lock();		//如果mu1没上锁,就上锁,执行printsecond,如果此时是锁住的则等待其他线程执行unlock
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        mu1.unlock();	//把刚才锁住的线程解锁
        mu2.unlock();	//给tired提供解锁操作
        
    
}

    void third(function<void()> printThird) {
        mu2.lock();		//同上,如果没上锁,就锁住执行,如果上锁了就等待其他线程执行解锁操作
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
        mu2.unlock();	//锁住了就解锁,代表执行完毕
        
    }



};

mutex

mutex又称互斥量,用于提供对共享变量的互斥访问。mutex包含于头文件#include <mutex>

| 序号 | 名称| 用途 |
| ------------ | ------------ | ------------ | ------------ |
| 1 | mutex | 最基本也是最常用的互斥类 |
| 2 | recursive_mutex| 同一线程内可递归(重入)的互斥类 |
| 3 | timed_mutex | 除具备mutex功能外,还提供了带时限请求锁定的能力 |
| 4 | recursive_timed_mutex | 同一线程内可递归(重入)的timed_mutex|

操作

lock

锁住互斥量。调用lock时有三种情况:

  • 如果互斥量没有被锁住,则调用线程将该mutex锁住,直到调用线程调用unlock释放。
  • 如果mutex已被其它线程lock,则调用线程将被阻塞,直到其它线程unlock该mutex。
  • 如果当前mutex已经被调用者线程锁住,则std::mutex死锁,而recursive系列则成功返回。

try_lock

尝试锁住mutex,调用该函数同样也有三种情况:

  • 如果互斥量没有被锁住,则调用线程将该mutex锁住(返回true),直到调用线程调用unlock释放。
  • 如果mutex已被其它线程lock,则调用线程将失败,并返回false。
  • 如果当前mutex已经被调用者线程锁住,则std::mutex死锁,而recursive系列则成功返回true。

unlock

解锁mutex,释放对mutex的所有权。值得一提的时,对于recursive系列mutex,unlock次数需要与lock次数相同才可以完全解锁。

try_lock_for, try_lock_until

这两个函数仅用于timed系列的mutex(std::timed_mutex, std::recursive_timed_mutex),函数最多会等待指定的时间,如果仍未获得锁,则返回false。除超时设定外,这两个函数与try_lock行为一致。

lock_guard

lock_guard利用了C++ RAII的特性,在构造函数中上锁,析构函数中解锁。

unique_lock

ock_guard提供了简单上锁、解锁操作,但当我们需要更灵活的操作时便无能为力了。这些就需要unique_lock上场了。unique_lock拥有对Mutex的所有权,一但初始化了unique_lock,其就接管了该mutex, 在unique_lock结束生命周期前(析构前),其它地方就不要再直接使用该mutex了。

try_lock

当有多个mutex需要执行try_lock时,该函数提供了简便的操作。try_lock会按参数从左到右的顺序,对mutex顺次执行try_lock操作。当其中某个mutex.try_lock失败(返回false或抛出异常)时,已成功锁定的mutex都将被解锁。
需要注意的是,该函数成功时返回-1, 否则返回失败mutex的索引,索引从0开始计数。

posted @ 2021-04-09 11:59  shenlei_blog  阅读(109)  评论(0)    收藏  举报