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()))
{
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);
对多个锁进行上锁,该函数是阻塞的。另,它保证发生异常的情况下已经上锁的锁会被解锁。
C++标准库之mutex的更多相关文章
- Go 标准库 —— sync.Mutex 互斥锁
Mutex 是一个互斥锁,可以创建为其他结构体的字段:零值为解锁状态.Mutex 类型的锁和线程无关,可以由不同的线程加锁和解锁. 方法 func (*Mutex) Lock func (m *Mut ...
- Python标准库08 多线程与同步 (threading包)
Python主要通过标准库中的threading包来实现多线程.在当今网络时代,每个服务器都会接收到大量的请求.服务器可以利用多线程的方式来处理这些请求,以提高对网络端口的读写效率.Python是一种 ...
- STL笔记(6)标准库:标准库中的排序算法
STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...
- 用CAS操作实现Go标准库中的Once
Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ...
- Boost程序库完全开发指南——深入C++“准”标准库(第3版)
内容简介 · · · · · · Boost 是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库,有着“C++‘准’标准库”的美誉. Boost 由C++标准委员会部分成员所设立的Bo ...
- Python学习笔记16:标准库多线程(threading包裹)
Python主要是通过标准库threading包来实现多线程. 今天,互联网时代,所有的server您将收到大量请求. server要利用多线程的方式的优势来处理这些请求,为了改善网络port读写效率 ...
- go标准库的学习-io
参考https://studygolang.com/pkgdoc 导入方式: import "io" o包提供了对I/O原语的基本接口.本包的基本任务是包装这些原语已有的实现(如o ...
- 通过atomic_flag简单自旋锁实现简单说明标准库中锁使用的memory_order
在使用标准库中的加锁机制时,例如我们使用std::mutex,写了如下的代码(下面的代码使用condition_variable可能更合适) std::mutex g_mtx; int g_resNu ...
- C++标准库头文件<bits/stdc++.h>
在使用GNU GCC Compiler的时候,你可以包含一个头文件<bits/stdc++.h>,便可以使用C++中的各种标准库,而不用一个一个包含进来. 这在acm比赛中是一种常用的做法 ...
随机推荐
- UNIX网络编程读书笔记:套接口选项
概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...
- Java网络编程-HTTP协议
HTTP协议的定义 这篇文章暂时不研究HTTP底层的TCP/IP的握手和挥手过程,只从表面的交互流程分析HTTP协议. HTTP英文全称是Hypertext Transfer Protpcol,也就是 ...
- CentOS 6.2下二进制安装 MySQL 5.6
在CentOS 6.2上 二进制方式安装 MySQL5.6二进制包 可以参考这篇文章: http://www.cnblogs.com/xiaoit/p/3988640.html 一路配置下来很顺利.. ...
- 从头认识多线程-1.9 迫使线程停止的方法-return法
这一章节我们来讨论一下还有一种停止线程的方法-return 1.在主线程上面return,是把全部在执行的线程都停掉 package com.ray.deepintothread.ch01.topic ...
- CentOS连接网络注意事项
连接网络,系统中这两个服务需要启动 可以看到右上角网络连接成功了
- Android中的Layout_weight终极研究
以前在做UI布局时,也经常用Layout_weight属性,有时会遇到莫名其妙的布局问题,但总没研究懂.一直想做深入分析,但总是没耐心.遇到问题就找替代方法解决,但终非长久之计.这次下决心给它弄透! ...
- No persister for nhibernate 解决下面的问题
在你的实体类对应的配置文件点右键选择属性,修改类型为:一直复制和嵌入的资源.就可以了.
- mfc获取控件在对话框上的位置
CRect rect; GetDlgItem(控件ID)->GetWindowRect(&rect);//获取控件的屏幕坐标ScreenToClient(&rect);//转换为 ...
- CMD查看进程ID并查杀进程
开始-运行,输入CMD打开命令行界面,输入命令netstat -ano 结束该进程C:\>taskkill /f /t /im Wiz.exe 根据进程ID杀 >taskkill /F / ...
- NPM 模块恩仇录
vue-clickoutside 点击元素以外的东西时会触发的事件.好东西.其实可以利用全局event来判断当前点击的对象来判断也一样.但这个显然更舒服 传送门:https://www.npmjs.c ...