C++11中新增了<mutex>,它是C++标准程序库中的一个头文件,定义了C++11标准中的一些互斥访问的类与方法等。

C++11标准库定义了4个互斥类:

std::mutex

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

  • 下面给出一个与 std::mutex 的小例子(http://www.cplusplus.com/reference/mutex/mutex/try_lock/):

// mutex::try_lock example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutexvolatile int counter (0); // non-atomic counter
std::mutex mtx;           // locks access to countervoid attempt_10k_increases () {for (int i=0; i<10000; ++i) {if (mtx.try_lock()) {   // only increase if currently not locked:++counter;mtx.unlock();}}
}int main ()
{std::thread threads[10];// spawn 10 threads:for (int i=0; i<10; ++i)threads[i] = std::thread(attempt_10k_increases);for (auto& th : threads) th.join();std::cout << counter << " successful increases of the counter.\n";return 0;
}

std::recursive_mutex

官方文档是这么说的:

recursive_mutex 类是同步原语,能用于保护共享数据免受个多线程同时访问。

recursive_mutex 提供排他性递归所有权语义:

  • 调用方线程在从它成功调用 lock 或 try_lock 开始的时期里占有 recursive_mutex 。此时期间,线程可以进行对 lock 或 try_lock 的附加调用。所有权的时期在线程调用 unlock 匹配次数时结束。

  • 线程占有 recursive_mutex 时,若其他所有线程试图要求 recursive_mutex 的所有权,则它们将阻塞(对于调用 lock )或收到 false 返回值(对于调用 try_lock )。

  • 可锁定 recursive_mutex 次数的最大值是未指定的,但抵达该数后,对 lock 的调用将抛出 std::system_error 而对 try_lock 的调用将返回 false 。

若 recursive_mutex 在仍为某线程占有时被销毁,则程序行为未定义。recursive_mutex 类满足互斥体 (Mutex) 和标准布局类型 (StandardLayoutType) 的所有要求。

用人话说就是:递归互斥锁可以被同一个线程多次加锁,以获得对互斥锁对象的多层所有权。例如,同一个线程多个函数访问临界区时都可以各自加锁,执行后各自解锁。std::recursive_mutex释放互斥量时需要调用与该锁层次深度相同次数的unlock(),即lock()次数和unlock()次数相同。可见,线程申请递归互斥锁时,如果该递归互斥锁已经被当前调用线程锁住,则不会产生死锁。

recursive_mutex 的使用场景之一是保护类中的共享状态,而类的成员函数可能相互调用。官方的小例子:

#include <iostream>
#include <thread>
#include <mutex>class X {std::recursive_mutex m;std::string shared;public:void fun1() {std::lock_guard<std::recursive_mutex> lk(m);shared = "fun1";std::cout << "in fun1, shared variable is now " << shared << '\n';}void fun2() {std::lock_guard<std::recursive_mutex> lk(m);shared = "fun2";std::cout << "in fun2, shared variable is now " << shared << '\n';fun1(); // 递归锁在此处变得有用std::cout << "back in fun2, shared variable is " << shared << '\n';};
};int main()
{X x;std::thread t1(&X::fun1, &x);std::thread t2(&X::fun2, &x);t1.join();t2.join();
}

可以看出fun2调用的fun1,他们都对recursive_mutex m 加锁,如果不是recursive的,那么这里会产生死锁。假设fun2拿到了锁,然后调用fun1又要去拿锁,又不是recursive的,那么就会hang在fun1里边。

std::time_mutex

官方文档是这么说的:

recursive_timed_mutex 是同步原语,能用于保护共享数据免受从多个线程同时访问。

以类似 std::recursive_mutex 的方式, recursive_timed_mutex 提供排他性递归所有权语义。另外, recursive_timed_mutex 通过 try_lock_for 与 try_lock_until 方法,提供带时限地试图要求 recursive_timed_mutex 所有权的能力。

recursive_timed_mutex 类满足定时互斥体 (TimedMutex) 和标准布局类型 (StandardLayoutType) 的所有要求。

换成人话说:

std::time_mutex 比 std::mutex 多了两个成员函数,try_lock_for(),try_lock_until()。

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

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

举个try_lock_for的小例子:

#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <sstream>std::mutex cout_mutex; // 控制到 std::cout 的访问
std::timed_mutex mutex;void job(int id)
{using Ms = std::chrono::milliseconds;std::ostringstream stream;for (int i = 0; i < 3; ++i) {if (mutex.try_lock_for(Ms(100))) {stream << "success ";std::this_thread::sleep_for(Ms(100));mutex.unlock();} else {stream << "failed ";}std::this_thread::sleep_for(Ms(100));}std::lock_guard<std::mutex> lock(cout_mutex);std::cout << "[" << id << "] " << stream.str() << "\n";
}int main()
{std::vector<std::thread> threads;for (int i = 0; i < 4; ++i) {threads.emplace_back(job, i);}for (auto& i: threads) {i.join();}
}

可能的输出:

[0] failed failed failed [3] failed failed success [2] failed success failed [1] success failed success

std::recursive_timed_mutex

这个就好说的,就是叠加recursive 和time两大神功的mutex。

std::mutex相关推荐

  1. C++多线程:互斥变量 std::mutex

    文章目录 描述 成员函数 总结 描述 头文件 <mutex> 使用 std::mutex <variable> 简介 mutex是一种多线程变成中的同步原语,它能够让共享数据不 ...

  2. C++11 并发指南三(std::mutex 详解)

    上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...

  3. C++多线程中互斥量std::mutex与模板类std::lock_guard

    一. 互斥量std::mutex C++中通过实例化std::mutex创建互斥量实例,通过成员函数lock()对互斥量上锁,unlock()进行解锁.C++中与std::mutex相关的类(包括锁类 ...

  4. 【多线程】多线程锁住的是什么、std::lock_guard<std::mutex> locker(mutex_)

    通常不直接使用 mutex,lock_guard更加安全, 更加方便. lock_guard简化了 lock/unlock 的写法, lock_guard在构造时自动锁定互斥量, 而在退出作用域时会析 ...

  5. linux的mutex状态查询命令,如何断言std :: mutex是否已锁定?

    使用GCC 4.8.2(在Linux / Debian / Sid 64位上)或GCC 4.9(在C ++ 11中可用)-我有一些互斥锁 std::mutex gmtx; 实际上,它是static某个 ...

  6. std::mutex详解

    Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文件中,所以如果你需要使用 std::mutex,就必须包含 <mute ...

  7. std::atomic和std::mutex区别

    ​std::atomic介绍​ ​模板类std::atomic是C++11提供的原子操作类型,头文件 #include<atomic>.​在多线程调用下,利用std::atomic可实现数 ...

  8. Multi-thread--C++11中std::mutex的使用

    C++11中新增了<mutex>,它是C++标准程序库中的一个头文件,定义了C++11标准中的一些互斥访问的类与方法等.其中std::mutex就是lock.unlock.std::loc ...

  9. C++11 std::mutex使用以及std::lock_guard自动解锁避免忘记解锁

    文章目录 **std::mutex** std::mutex 的成员函数 示例 **std::lock_guard** std::mutex 头文件是<mutex>,mutex是用来保证线 ...

最新文章

  1. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第8篇]交互式的定义如何帮助计算和IP类问题是什么
  2. 栈溢出脚本_漏洞练习之网络编程与堆栈溢出技术
  3. 甜蜜暴击情人节海报PSD分层模板|让人眼前一亮
  4. JavaScript 01
  5. WebForm中 页面传参的总结
  6. SVN branch分支管理
  7. AD637 有效值检测
  8. ImportError: cannot import name ‘_validate_lengths‘ from ‘numpy.lib.arraypad的解决方法(简单粗暴)
  9. 快速隐藏所有桌面图标快捷键是什么?
  10. permissionerror winerror 5 拒绝访问。
  11. ORMLite 数据库的使用--二次封装
  12. 7、Java基础——从控制台输入:Scanner类的的用法、数据类型转换、字符型的运算、print与println的区别、Java中的转义字符
  13. 微信小程序开发学习—Day1
  14. chmod -R 777使用.
  15. 国内的部分免费论坛程序汇总
  16. J2EE-2 helloworld
  17. 【漏洞报送】泛微E-Office存在SQL注入漏洞(CNVD-2022-43246)
  18. 北航计算机历年专业,北航计算机考研专业课历年真题(2003-2008).doc
  19. mysql弱口令检测_MySQL数据库弱口令探测
  20. 【C++】C++11

热门文章

  1. modules runAllManagedModulesForAllRequests=true /(转1)
  2. 在ubuntu 14.04 编译android 2.3.1 错误解决办法
  3. 转自JIM Wang:把 isv.config.xml 按钮事件移动到 entity.onload()
  4. php注册登录遍写入 遍验证,在文件指定行中写入内容的php...-自动注册登录验证机制的php代...-php中出现Undefined index报错的修复方法_169IT.COM...
  5. [网络安全自学篇] 二十九.文件上传和IIS6.0解析问题及防御原理(二)
  6. [python爬虫] 爬取图片无法打开或已损坏的简单探讨
  7. [Android] 底部菜单布局+PopupWindows实现弹出菜单功能(初级篇)
  8. iOS之“支付宝支付”开发流程
  9. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1071:菲波那契数
  10. 《算法竞赛入门经典》 例题5-1 大理石在哪(Where is the Marble,UVa 10474)