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比赛中是一种常用的做法 ...
随机推荐
- vb.net Bitmap Drawing
Public Class Form1 Dim BMP As New Drawing.Bitmap(640, 480) Dim GFX As Graphics = Graphics.FromImage( ...
- Android-PullToRefresh(一)
先讲下这篇写啥东西,也就是这家伙(chrisbanes)写的一个上拉下拉刷新的Demo,连接https://github.com/fengcunhan/Android-PullToRefresh 东西 ...
- SuperMap iManager跨网段配置许可
作者:非法小恋 1.开启Docker容器1947映射 修改docker-compose.yml,在iManager的ports添加- "1947:1947" 2.重启iManage ...
- C#实现分片上传文件
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO ...
- TCP的发送缓冲区和接收缓冲区
TCP协议是作用是用来进行端对端数据传送的,那么就会有发送端和接收端,在操作系统有两个空间即user space和kernal space. 每个Tcp socket连接在内核中都有一个发送缓冲区和接 ...
- Json序列化之.NET开源类库Newtonsoft.Json
上代码: using System; using System.Collections; using System.Collections.Generic; using System.IO; usin ...
- csrf跨站请求攻击
浅谈CSRF攻击方式 http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
- 错了:用流量能够放肆,有wifi则要节制
网络上疯传的节制体中就有这么一句:有wifi就会放肆,但用流量就会节制.榜上有名,也说明了人们对wifi网络的需求.尤其是免费wifi.从对无线网络需求方面,毫无疑问,可是从还有一角度,我则觉得是流量 ...
- node.js 连接 mysql
var mysql = require("mysql"); var connection = mysql.createConnection({ host: '127.0.0.1', ...
- Unity3D动画面板编辑器状态属性对照表
不推荐用AnimationUtility.SetEditorCurve问题很多,推荐AnimationCurve.AddKey.通过AnimationUtility.GetAllCurves可以获得编 ...