C++11std::mutex的使用-创新互联

std::mutex
  • Mutex 系列类(四种)
    • std::mutex,最基本的 Mutex 类
    • std::recursive_mutex,递归 Mutex 类
    • std::time_mutex,定时 Mutex 类。
    • std::recursive_timed_mutex,定时递归 Mutex
  • Lock 类(两种)
    • std::lock_guard,与 Mutex RAII 相关,方便线程对互斥量上锁。
    • std::unique_lock,与 Mutex RAII 相关,方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。
  • 其他类型
    • std::once_flag(提供一种方式,可以保证其实例绑定的函数,能且仅能被执行一次)
    • adopt_lock_t(假设调用方线程已拥有互斥的所有权)
    • std::defer_lock_t(不获得互斥的所有权)
    • std::try_to_lock_t(尝试获得互斥的所有权而不阻塞)
  • 相关函数
    • std::try_lock,尝试同时对多个互斥量上锁。
    • std::lock,可以同时对多个互斥量上锁。
    • std::call_once,如果多个线程需要同时调用某个函数,call_once 可以保证多个线程对该函数只调用一次。

为罗平等地区用户提供了全套网页设计制作服务,及罗平网站建设行业解决方案。主营业务为成都网站制作、成都网站设计、外贸营销网站建设、罗平网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
Mutex 系列类(四种)
  • std::mutex,最基本的 Mutex 类

独占互斥量,只能加锁一次
std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。


std::mutex成员函数:

  • 构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
  • lock(),调用线程将锁住该互斥量
  • unlock(), 解锁,释放对互斥量的所有权。
  • try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。

  • std::recursive_mutex,递归 Mutex 类

递归的独占互斥量,允许同一个线程,同一个互斥量,多次被lock,用法和非递归的一样 跟windows的临界区是一样的,但是调用次数是有上限的,效率也低一些
和 std::mutex 不同的是,
std::recursive_mutex 允许同一个线程对互斥量多次上锁(即递归上锁),来获得对互斥量对象的多层所有权,
std::recursive_mutex 释放互斥量时需要调用与该锁层次深度相同次数的 unlock(),可理解为 lock() 次数和 unlock() 次数相同.


  • std::time_mutex,定时 Mutex 类。

带超时的互斥量,独占互斥量 这个就是拿不到锁会等待一段儿时间,但是超过设定时间,就继续执行
std::time_mutex 比 std::mutex 多了两个成员函数,try_lock_for(),try_lock_until()。

template< class Rep, class Period >bool try_lock_for( const
std::chrono::duration& timeout_duration ); 
//  (C++11 起) 
template< class Rep, class Period >bool try_lock_for( const
std::chrono::duration& timeout_duration ); 
//  (C++11 起)
  • try_lock_for:尝试锁定互斥,若互斥在指定的时限时期中不可用则返回。
  • try_lock_until:尝试锁定互斥,若直至抵达指定时间点互斥不可用则返回。

参数
timeout_duration - 要阻塞的大时长
返回值
若成功获得锁则为 true ,否则为 false 。
异常
执行期间时钟、时间点或时长可能抛出的异常(标准库提供的时钟、时间点和时长决不抛出)


  • std::recursive_timed_mutex,定时递归 Mutex

带超时的,递归的,独占互斥量,允许同一个线程,同一个互斥量,多次被lock,用法和非递归的一样


Lock 类(两种)
  • std::lock_guard,与 Mutex RAII 相关,方便线程对互斥量上锁。
  • lock_guard功能与std::mutex的lock与unlock功能相同。 不同的是,lock_guard析构时会自动解锁,使用时无须unlock。这就需要我们将共享资源的访问封装成尽可能小的函数,避免加锁时间过长。
  • 为了防止在线程使用mutex加锁后异常退出导致死锁的问题,建议使用lock_guard代替mutex.
  • std::lock_guard类的构造函数禁用拷贝构造,且禁用移动构造。std::lock_guard类除了构造函数和析构函数外没有其它成员函数

注意,lock_guard对象不以任何方式管理互斥对象的生存期:互斥对象的生存期至少要延长到锁它的lock_guard被销毁。


  • std::unique_lock,与 Mutex RAII 相关,方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。
  • unique_lock是个类模板,工作中,一般lock_guard(推荐使用);lock_guard取代了mutex的lock()和unlock();
  • unique_locklock_guard灵活很多,效率上差一点,内存占用多一点。
  • std::unique_lock可以在构造时传递第二个参数用于管理互斥量,且能传递不同域中互斥量所有权。
  • unique_lock私有成员为指针 _Mutex /*_Pmtx,指向传递进来的互斥量,lock_guard私有成员为引用_Mutex& _MyMutex,引用传递进的互斥量。这就决定了unique_lock能够实现传递互斥量的功能。
  • unique_lock的用法比较多,如果对锁的需求比较简单推荐使用lock_guard。当需要超时或者手动解锁等功能,可以考虑使用unique_lock

不同的情况可使用对应的构造创建对象

unique_lock(mutex, adopt_lock_t) //传递被使用过的mutex,且已经被上过锁,通过。无上锁动作,不阻塞。

unique_lock(mutex, defer_lock_t) //传递被使用过的mutex,未被上过锁。无上锁动作,不阻塞。

unique_lock(mutex, try_to_lock_t) //任何状态的mutex。尝试上锁,不阻塞。

unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>&
_Rel_time) //在指定时间长内尝试获取传递的mutex的锁返回。若无法获取锁,会阻塞到指定时间长。

unique_lock(mutex_type& m,std::chrono::time_pointconst& absolute_time) //在给定时间点尝试获取传递的mutex锁返回。若无法获取锁,会阻塞到指定时间点。

unique_lock(unique_lock&& _Other)
//将已经创建的unique_lock锁的所有权转移到新的锁。保持之前锁的状态,不阻塞 ```

unique_lock的成员函数
unique_lock除了拥有跟std::mutex一样的三个成员函数意外,还提供release()函数。
release()返回它所管理的mutex对象指针,并释放所有权;也就是说,这个unique_lock和mutex不再有关系。严格区分unlock()与release()的区别,不要混淆。

  std::unique_locksbguard(my_mutex);
      std::mutex *ptx = sbguard.release(); //现在你有责任自己解锁了
      msgRecvQueue.push_back(i);
      ptx->unlock(); //自己负责mutex的unlock了

unique_lock所有权的传递

std::unique_lockstd::mutex sbguard(my_mutex);//所有权概念
std::unique_lockstd::mutex sbguard1(my_mutex);
std::unique_lockstd::mutex sbguard2(sbguard1);//此句是非法的,复制所有权是非法
//sbguard拥有my_mutex的所有权;sbguard可以把自己对mutex(my_mutex)的所有权转移给其他的unique_lock对象;
//所以unique_lock对象这个mutex的所有权是可以转移,但是不能复制。

所有权的传递的方法

方法1 :std::move()
方法2:return std:: unique_lockstd::mutex


其他类型
  • std::once_flag(提供一种方式,可以保证其实例绑定的函数,能且仅能被执行一次)
  • adopt_lock_t(假设调用方线程已拥有互斥的所有权)
  • Value used as possible argument to the constructor of unique_lock or lock_guard.

  • objects constructed with adopt_lock do not lock the mutex object on construction, assuming instead that it is already locked by the current thread.

  • The value is a compile-time constant that carries no state, and is merely used to disambiguate between constructor signatures.

  • adopt_lock_t is an empty class.

  • std::defer_lock_t(不获得互斥的所有权)
  • Value used as possible argument to unique_lock’s constructor.

  • unique_lock objects constructed with defer_lock do not lock the mutex object automatically on construction, initializing them as not owning a lock.

  • The value is a compile-time constant that carries no state, and is merely used to disambiguate between constructor signatures.

  • defer_lock_t is an empty class.

  • std::try_to_lock_t(尝试获得互斥的所有权而不阻塞)
  • Value used as possible argument to unique_lock’s constructor.

  • unique_lock objects constructed with try_to_lock attempt to lock the mutex object by calling its try_lock member instead of its lock member.

  • The value is a compile-time constant that carries no state, and is merely used to disambiguate between constructor signatures.


相关函数
std::try_lock,尝试同时对多个互斥量上锁。
std::lock,可以同时对多个互斥量上锁。
std::call_once,如果多个线程需要同时调用某个函数,call_once 可以保证多个线程对该函数只调用一次。
templatevoid call_once (once_flag&flag, Fn&& fn, Args&&... args);

flag:仅可执行一次的对象,其生命周期要比所在的线程长
Fn:执行函数
args:执行函数的可变参数

当多个线程使用同一个flag对象去调用函数call_once时,仅有一个线程可以真正的完成对函数Fn的调用,其他的线程会被阻塞,直到函数Fn返回.

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:C++11std::mutex的使用-创新互联
地址分享:http://abwzjs.com/article/pgoej.html