当前位置: 首页 > news >正文

【C++11并发】mutex 笔记

简介

在多线程中往往需要访问临界资源,C++11为我们提供了mutex等相关类来保护临界资源,保证某一时刻只有一个线程可以访问临界资源。主要包括各种mutex,他们的命名大都是xx_mutex。以及RAII风格的wrapper类,RAII就是一般在构造的时候上锁,在析构的时候解锁。

C++11提供的锁类型有三个:

  • mutex,头文件:
  • timed_mutex,头文件:
  • recursive_mutex,头文件:
  • recursive_timed_mutex,头文件:<shared_mutex>

C++11提供的RAII风格的wrapper类有两个:

  • lock_guard,头文件:
  • unique_lock,头文件:

std::mutex

mutex提供的方法不过,主要有lock和unlock
在这里插入图片描述
mutex只有默认构造方法,不允许拷贝构造,目前也没有提供移动构造

constexpr mutex() noexcept;
mutex( const mutex& ) = delete;

lock和try_lock的区别是,lock会阻塞当前线程,而try_lock不会,如果没有获取到锁,则返回false,如果获取到则返回true。

std::timed_mutex

相比于mutex,timed_mutex多了try_lock_for和try_lock_until两个方法。try_lock_for表示花多长时间尝试获取锁,如果超过时长则失败。try_lock_until表示尝试获取锁到什么时候,如果超过指定时间点则失败。
在这里插入图片描述

try_lock_for的函数声明如下,两个模板参数都是形参timeout_duration的,Rep表示保存时间段的类型,Period表示单位,比如秒,毫秒等。详细参考:chrono。try_lock_for表达的意思就是:阻塞获取锁,最长阻塞timeout_duration时间。如果期间获取到了锁,则返回true,否则返回false。如果timeout_duration小于等于0,try_lock_for的行为就和try_lock一样。

template< class Rep, class Period >
bool try_lock_for( const std::chrono::duration<Rep, Period>& timeout_duration );

例子:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>void run(std::timed_mutex &mutex)
{if (mutex.try_lock_for(std::chrono::milliseconds(500))) {std::cout << "获得了锁" << std::endl;} else {std::cout << "未获得锁" << std::endl;}
}int main() {std::timed_mutex mutex;mutex.lock();std::thread thread(run, std::ref(mutex));thread.join();mutex.unlock();return 0;
}//输出:未获得锁

try_lock_until的函数声明如下,两个模板参数都是形参timeout_time的,Clock是始终类型,Duration就是前面的std::chrono::duration。try_lock_until表达的意识就是:阻塞获取锁,一直阻塞到timeout_time这个时间点。如果期间获取到了锁,则返回true,否则返回false。time_point 参考。

template< class Clock, class Duration >
bool try_lock_until( const std::chrono::time_point<Clock, Duration>& timeout_time );

例子:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>void run(std::timed_mutex &mutex)
{std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();if (mutex.try_lock_for(now + std::chrono::milliseconds(500))) {std::cout << "获得了锁" << std::endl;} else {std::cout << "未获得锁" << std::endl;}
}int main() {std::timed_mutex mutex;mutex.lock();std::thread thread(run, std::ref(mutex));thread.join();mutex.unlock();return 0;
}//输出:未获得锁

std::recursive_mutex

recursive_mutex和mutex的区别就在“recursive“,recursive_mutex允许同一个线程多次lock,当然需要相同次数的unlock。c++没有规定最多可以调用多少次,如果到达了最大lock次数,lock方法会抛出异常(std::system_error),try_lock会返回false。
在这里插入图片描述

std::recursive_timed_mutex

recursive_timed_mutex就是recursive_mutex和timed_mutex的结合体,提供的方法如下:
在这里插入图片描述

std::lock_guard

lock_guard是一个RAII风格mutex wrapper,即就是在他析构的时候,会解锁他关联的mutex。一般在构造lock_guard的时候,给mutex上锁,当然也有例外,具体得看在调用lock_guard的构造方法时传的参数。
下面是lock_guard提供的方法
在这里插入图片描述
构造方法可用的有两个

explicit lock_guard( mutex_type& m );                // 在构造lock_guard的时候调用m的lock方法,在析构的时候调用m的unlock方法
lock_guard( mutex_type& m, std::adopt_lock_t t );    // 只是关联m,但是不调用m的lock方法,在析构的时候调用m的unlock方法
lock_guard( const lock_guard& ) = delete;            // 禁止拷贝构造lock_guard

std::unique_lock

相比于lock_guard,unique_lock提供了更强大的功能,虽然不能拷贝,但是可以移动。处理支持mutex的所有操作外,还可以支持mutex延迟上锁,尝试上锁等。lock_guard提供的方法有:
在这里插入图片描述
unique_lock提供的构造方法比较多:

unique_lock() noexcept;    // 构造一个不关联mutex的unique_lock对象,他可以通过移动拷贝操作符关联到一个mutex,或者调用swap方法
unique_lock( unique_lock&& other ) noexcept;    // 移动构造
explicit unique_lock( mutex_type& m );          // 构造unique_lock的时候,调用m.lock()
unique_lock( mutex_type& m, std::defer_lock_t t ) noexcept;    // 仅关联m,但是不调用m的lock方法
// 关联m,并且调用m的try_lock方法,当然前提是m有try_lock方法,如果没有,则行为是未定义的。
// try_lock可能失败,返回false。unique_lock的构造方法没有返回值,我们怎么知道m有没有上锁成功。
// 调用unique_lock的owns_lock方法,他返回bool,可以知道m有没有上锁成功。具体可以参考例子
unique_lock( mutex_type& m, std::try_to_lock_t t );  
// 关联已经上锁的m,如果m没有上锁,则行为未定义  
unique_lock( mutex_type& m, std::adopt_lock_t t );// 构造unique_lock的时候,关联m,并且执行m.try_lock_for(timeout_duration)。
// m上锁有没有成功,仍然可以通过unique_lock的owns_lock方法获取
template< class Rep, class Period >
unique_lock( mutex_type& m, const std::chrono::duration<Rep, Period>& timeout_duration );// 和上一个方法类似,只不过执行的是m.try_lock_until(timeout_time)
template< class Clock, class Duration >
unique_lock( mutex_type& m, const std::chrono::time_point<Clock, Duration>& timeout_time );

try_to_lock的例子:

#include <iostream>
#include <mutex>std::mutex mtx;void fun() {std::unique_lock<std::mutex> guard(mtx, std::try_to_lock);if (m_guard1.owns_lock()) {std::cout << "try_to_lock success" << std::endl;} else {std::cout << "try_to_lock failed" << std::endl;}
}

当unique_lock对象成功关联到了mutex,并且他获得了锁,则在析构的时候调用mutex的unlock方法。

unique_lock仅支持移动拷贝赋值操作符

unique_lock& operator=( unique_lock&& other );

unique_lock还提供了获取mutex的方法,在调用unique_lock提供的各种lock类方法时,就如同mutex()->lock()

mutex_type* mutex() const noexcept;

unique_lock还提供了unlock方法,当调用这个方法的时候,会调用mutex的unlock方法,并且unique_lock释放mutex,即不再关联当前mutex。当时当调用unlock方法时,没有关联到mutex,或者mutex没有获得锁,则会抛出std::system_error异常。

void unlock();

unique_lock的release方法只是与关联的mutex断开关联,并不会调用mutex的unlock方法

mutex_type* release() noexcept;

bool操作符,相当于调用owns_lock(),具体使用参考如下实例:

explicit operator bool() const noexcept;
#include <iostream>
#include <mutex>
#include <thread>class Test {
public:void fun() {std::unique_lock<std::mutex> lck(m_mtx);if (bool(lck)) {std::cout << "lock succ: bool(lck)" << std::endl;}if ((bool)lck) {std::cout << "lock succ: (bool)lck" << std::endl;}if (lck) {std::cout << "lock succ: lck" << std::endl;}}private:std::mutex m_mtx;
};int main() {Test test;std::thread thread(&Test::fun, &test);thread.join();return 0;
}/** 输出结果* lock succ: bool(lck)* lock succ: (bool)lck* lock succ: lck*/

相关文章:

【C++11并发】mutex 笔记

简介 在多线程中往往需要访问临界资源&#xff0c;C11为我们提供了mutex等相关类来保护临界资源&#xff0c;保证某一时刻只有一个线程可以访问临界资源。主要包括各种mutex&#xff0c;他们的命名大都是xx_mutex。以及RAII风格的wrapper类&#xff0c;RAII就是一般在构造的时…...

洛谷 P5635 【CSGRound1】天下第一

原址链接 P5635 【CSGRound1】天下第一 先看标签 搜索&#xff1f;模拟&#xff1f;用不着这么复杂 创建函数a(int x,int y,int p) a(int x,int y,int p){if(x<0){return 1;}x (xy)%p;if(y<0){return 2;}y (xy)%p;return a(x,y,p); }写入主函数 #include<iostrea…...

如何通过Navicat远程访问宝塔面板安装的MySQL数据库

Navicat报错信息&#xff1a; 错误代码 1045 Access denied for user ‘root’’219.144.205.81’ (using password:YES) —— 没有权限的访问的报错 1.宝塔面板 > 放行端口:3306 2.阿里云安全组 > 放行端口:3306 3.配置mysql3306端口 4.使用Xshell 链接服务器 m…...

【硅谷甄选】导航守卫(进度条,网页标题,路由鉴权)

import setting from /setting import router from /router // 任意路由切换实现进度条业务&#xff1a; nprogress插件 import nprogress from nprogress // js插件在ts中的报错 // 引入进度条样式 import nprogress/nprogress.css // 表示在加载进度条时不显示加载小图标 np…...

OpenHarmony—TypeScript到ArkTS约束说明

对象的属性名必须是合法的标识符 规则&#xff1a;arkts-identifiers-as-prop-names 级别&#xff1a;错误 在ArkTS中&#xff0c;对象的属性名不能为数字或字符串。通过属性名访问类的属性&#xff0c;通过数值索引访问数组元素。 TypeScript var x { name: x, 2: 3 };c…...

蓝桥杯——每日一练(简单题)

题目 有n个整数&#xff0c;使前面各数顺序向后移m个位置&#xff0c;最后m个数变成前面m个数。写一函数&#xff1a;实现以上功能&#xff0c;在主函数中输入n个数和输出调整后的n个数。 解析 一、list&#xff08;&#xff09;函数配合map&#xff08;&#xff09;函数获得…...

css设置不可点击

文章目录 一、前言二、MDN三、使用四、注意五、总结六、最后 一、前言 在网页开发中&#xff0c;经常会遇到一种情况&#xff0c;就是需要将某个元素的点击事件屏蔽&#xff0c;使其在用户点击时没有任何反应。这时候&#xff0c;我们可以通过CSS的pointer-events属性设置为no…...

fastapi学习

fastapi框架 fastapi&#xff0c;一个用于构建 API 的现代、快速&#xff08;高性能&#xff09;的web框架。 fastapi是建立在Starlette和Pydantic基础上的&#xff0c;Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工…...

【代码随想录-数组】长度最小的子数组

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…...

多表查询练习题

student表: score表: 向student表插入记录: 向score表插入记录: 1.查询student表的所有记录 SELECT * FROM student;2.查询student表的第2条到4条记录 SELECT * FROM student LIMIT 1,3;3.从student表查询所有学生的学号&#xff08;id&#xff09;、姓名&#xff08;name&…...

SpringBoot之时间数据前端显示格式化

背景 在实际我们通常需要在前端显示对数据操作的时间或者最近的更新时间&#xff0c;如果我们只是简单的使用 LocalDateTime.now()来传入数据不进行任何处理那么我们就会得到非常难看的数据 解决方式&#xff1a; 1). 方式一 在属性上加上注解&#xff0c;对日期进行格式…...

Maven讲解

介绍 Maven是一个流行的构建工具和项目管理工具&#xff0c;它主要用于Java项目的构建、依赖管理和项目报告生成。Maven通过提供一致的项目结构、自动化的构建过程和强大的依赖管理&#xff0c;简化了项目的开发和维护过程。 下面是一些Maven的主要特点和用途&#xff1a; 项…...

Redis2-事务 连接Java 整合springboot 注解缓存

一、订阅和发布 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 Redis的发布和订阅 客户端订阅频道发布的消息 频道发布消息 订阅者就可以收到消息 发布订阅的代…...

CHFS 文件服务器搭建小记

一、CHFS 简介 摘自官网&#xff1a;http://iscute.cn/chfs CuteHttpFileServer/chfs 是一个免费的、HTTP协议的文件共享服务器&#xff0c;使用浏览器可以快速访问。它具有以下特点&#xff1a; 单个文件&#xff0c;核心功能无需其他文件跨平台运行&#xff0c;支持主流平台…...

vue中图片不显示问题 - vue中静态资源加载

文章目录 vue中图片不显示问题静态资源URL 转换规则webpack 静态资源处理 图片不显示问题问题描述解决办法1&#xff1a;使用require引入require is not defined 解决办法2&#xff1a;使用import引入解决办法3&#xff1a;将图片放进公共文件夹static或public vue中图片不显示…...

IP报文格式

IP报文格式 报文格式 图1 IP头格式 表1 IP头字段解释 字段长度含义Version4比特 4&#xff1a;表示为IPV4&#xff1b;6&#xff1a;表示为IPV6。IHL4比特首部长度&#xff0c;如果不带Option字段&#xff0c;则为20&#xff0c;最长为60&#xff0c;该值限制了记录路由选项。…...

k8s 进阶实战笔记 | Pod 创建过程详解

Pod 创建过程详解 ​ 初始状态0 controller-manager、scheduler、kubelet组件通过 list-watch 机制与 api-server 通信并检查资源变化 第一步 用户通过 CLI 或者 WEB 端等方式向 api-server 发送创建资源的请求&#xff08;比如&#xff1a;我要创建一个replicaset资源&…...

使用MMYOLO中yolov8训练自己VOC数据集实战

概述 MMYOLO是商汤公司基于PyTorch框架和YOLO系列算法开源的工具箱 - 目前支持的任务 目标检测旋转框目标检测 - 支持的算法 YOLOv5YOLOv6YOLOv7YOLOv8YOLOXRTMDetRTMDet-Rotated - 支持的数据集 COCO Dataset VOC Dataset CrowdHuman Dataset DOTA 1.0 Dataset 安装…...

解决方案 | 基于SFTP协议的文件传输断点续传Java实现方案

背景 因项目需要&#xff0c;我们服务每天都需要通过SFTP协议来对接上下游进行文件传输&#xff0c;但是对于一些大文件&#xff0c;在与第三方公司的服务器对接过程中很可能会因为网络问题或上下游服务器性能问题导致文件上传或者下载被中断&#xff0c;每次重试都需要重新对…...

web前端项目-动画特效【附源码】

文章目录 一&#xff1a;赛车游戏动画HTML源码&#xff1a;JS源码&#xff1a;CSS源码&#xff1a;&#xff08;1&#xff09;normalize.css&#xff08;2&#xff09;style.css 二&#xff1a;吉普车动画演示HTML源码&#xff1a;CSS源码&#xff1a;&#xff08;1&#xff09…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...