多线程(补充知识)

STL库,智能指针和线程安全

STL中的容器是否是线程安全的? 不是.
原因是, STL 的设计初衷是将性能挖掘到极致, 而一旦涉及到加锁保证线程安全,会对性能造成巨大的影响.
而且对于不同的容器, 加锁方式的不同, 性能可能也不同(例如hash表的锁表和锁桶).
因此 STL 默认不是线程安全. 如果需要在多线程环境下使用, 往往需要调用者自行保证线程安全.

智能指针是否是线程安全的?
对于 unique_ptr, 由于只是在当前代码块范围内生效, 因此不涉及线程安全问题.
对于 shared_ptr, 多个对象需要共用一个引用计数变量, 所以会存在线程安全问题.
但是标准库实现的时候考虑到了这个问题, 基于原子操作(CAS)的方式保证 shared_ptr 能够高效, 原子的操作引用计数.
即share_ptr也是线程安全的!但是注意,share_ptr是线程安全的,但并不意味着它所指向的资源也是线程安全的

其它锁介绍

悲观锁:
在每次取数据时,总是担心数据会被其他线程修改,所以会在取数据前先加锁(读锁,写锁,行锁等),当其他线程想要访问数据时,被阻塞挂起。
乐观锁:
每次取数据时候,总是乐观的认为数据不会被其他线程修改,因此不上锁。但是在更新数据前,会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式:版本号机制和CAS操作。
CAS操作:
当需要更新数据时,判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不等则失败,失败则重试,一般是一个自旋的过程,即不断重试

自旋锁

我们之前学的互斥锁,申请不到锁的时候,都会被挂起等待
那挂起等待的操作是由谁来完成的呢?
答案还是我们的OS(操作系统)老大.
阻塞或者唤醒一个线程对OS来说其实也会是一种负担,假如一个线程持有锁的时间很短,即OS刚让没有抢到锁的线程阻塞等待,还没等一会儿,持有锁的线程就说自己完成任务了,OS又要把刚阻塞等待的线程唤醒,这样效率就不高!
那有没有其它锁,一直轮询,看锁是否释放了,而不是阻塞等待?
答案是有的,就是我们接下来要介绍的自旋锁.
自旋锁的本质就是轮询,不达目的不罢休
线程获取不到自旋锁,并不会被阻塞等待,而是一直询问拿到锁的线程,什么时候好?一旦完成任务,释放锁,就立马获取锁,省下了线程状态切换的消耗
那什么时候采用互斥锁,什么时候采用自旋锁呢?
关键就是等待时间的长短,即访问临界区要花费多少时间
假如锁被占用的时间很短,那自旋的效果就很不错
反之,假如一直占用,来完成任务,那自旋的效果就大打折扣,白白浪费处理器资源

读写锁

在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。
相比较改写,它们读的机会反而高的多。通常而言,在读的过程中,往往伴随着查找的操作,中间耗时很长。给这种代码段加锁,会极大地降低我们程序的效率。
那么有没有一种方法,可以专门处理这种多读少写的情况呢? 有,那就是我们接下来要介绍的读写锁。

读者写者的"321"原则

3: 读者读者(无关系) 写者写者(互斥) 读者写者(互斥,同步)
2:读/写
1:交易场所

可以看到它和我们生产者消费者模型是非常相似的,唯一有一个重大区别就在于在cp问题中,消费者之间是互斥的,但是读者与读者是互相不影响的
原因在于消费者会拿走数据!但是读者并不会,只是访问相应的数据
理解读者写者问题,可以类比于我们小学时出黑板报
看黑板报的同学就是读者,出黑板报的同学就是写者
读者与读者间看黑板报互不影响
但是写者工作的时候,读者就不要看了,看了也没用,都没出完;同理,读者看的时候,写者就不要继续工作了,别人欣赏着,你突然将黑板报全部擦干净,只会得罪别人.

对应的接口

在这里插入图片描述

伪代码讲解原理

本质上是采用类似信号量的方式来实现的
在这里插入图片描述
最核心的其实就是保证
有一个读者读,写者不能写;但其它读者还可以进
所以最关键的还是读者这部分信号量的申请
在这里插入图片描述

写者饥饿问题

由上面的伪代码我们也可以发现
写者这个执行流是很容易长期持有不到锁的,只要reader_cnt一直不为0,也就是有读者读,写者就写不了
这也符合我们有些公共数据修改的机会比较少的场景(修改频率低)
一般默认读者优先,即有一把锁空闲出来,默认读者线程拿
我们还可以设置为写者优先策略,正在读的读者线程依旧可以继续读完,但是比写者线程晚到的读者线程就要往后排一下队.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/228387.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于LNMP快速搭建WordPress平台

目录 1 LNMP简介 2 WordPress简介 3 安装MySQL环境 3.1 安装MySQL 3.1.1 下载wget工具 3.1.2 下载MySQL官方yum源安装包 3.1.3 安装MySQL官方yum源 3.1.4 mysql安装 3.2 启动MySQL 3.3 获取默认密码 3.4 登录MySQL ​ 3.5 修改密码 3.6 创建WordPress数据库并授权 3.6.1 创…

医疗影像数据集—CT、X光、骨折、阿尔茨海默病MRI、肺部、肿瘤疾病等图像数据集

最近收集了一大波关于CT、X光等医疗方面的数据集包含骨折、阿尔茨海默病MRI、肺部疾病等类型的医疗影像数据,废话不多说,给大家逐一介绍!! 1、彩色预处理阿尔茨海默病MRI(磁共振成像)图像数据集 彩色预处理阿尔茨海默病MRI(磁共…

【沐风老师】3DMAX拼图建模工具MaxPuzzle2D插件使用方法详解

MaxPuzzle2D拼图建模工具使用帮助 MaxPuzzle2D拼图建模工具,拼图建模“彩虹系列”插件,是一款用MAXScript脚本语言开发的3dMax拼图建模小工具,可以创建2D或3D的拼图图形阵列。这让需要拼图建模的设计师大大节省了时间。 MaxPuzzle2D工具界面&…

电荷泵升压/降压电路

一、升压\降压电路原理分析 1、升压电路 电荷泵升压电路 VoutVa5V 5V_PLUS0V时,Va给C2充电,C2上节点电压比C2下节点电压高Va; 5V_PLUS5V时,C2电压不能突变,C2上节点电压依然比C2下节点电压高Va,但C2下节点…

C++单调向量(栈):好子数组的最大分数

作者推荐 利用广度优先或模拟解决米诺骨牌 题目 给你一个整数数组 nums &#xff08;下标从 0 开始&#xff09;和一个整数 k 。 一个子数组 (i, j) 的 分数 定义为 min(nums[i], nums[i1], …, nums[j]) * (j - i 1) 。一个 好 子数组的两个端点下标需要满足 i < k <…

STM32之模数转换器ADC

目录 1、ADC介绍 1.什么是ADC&#xff1f; ADC的全称是Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 2.ADC的性能指标 3.ADC特性 12位分辨率 4.ADC通道 5.ADC转换顺序 6.ADC触发方式 7.ADC转化时间 8.ADC转化模式 9.模拟看门狗 实验&#xff1a;使用ADC读…

SpringSecurity+JWT实现权限控制以及安全认证

一.简介 Spring Security 是 Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 认证&#xff1a;验证当前访问系统的是不是本系统的用户&#xff0c;并且要确认具体是哪个用户​ 授权&…

Cesium 添加一个立方体实体。

Cesium 添加一个立方体实体 初始化地球 viewer new Cesium.Viewer(content, {terrainProvider: Cesium.createWorldTerrain({requestVertexNormals: true,requestWaterMask: true})})添加一个立方体 const redBox viewer.entities.add({name: 一个红色的正方形,position: …

【08】Python运算符

文章目录 1.算术运算符2.赋值运算符3.条件运算符4.逻辑运算符5.比较运算符6.运算符的优先级本期博客中,我们将学习python中常用的运算符的用法。              1.算术运算符 1.加法运算符(+): a = 10 b = 5 c = a + b print(c

unity Toggle,初始时默认不选中,若选中则不可取消选中。不写码实现其效果

实现效果&#xff1a; 初始默认时&#xff1a; 选中时&#xff1a; 零代码实现&#xff1a; 步骤1 步骤2 步骤3

【专题】支持向量机(Support Vector Machines,SVM)

​​​​​ ​​ 支持向量机&#xff08;Support Vector Machines&#xff0c;SVM&#xff09;是一种强大的监督学习模型&#xff0c;常用于分类、回归和异常值检测任务。它的核心思想是通过构建一个最大间隔超平面来有效地分隔不同类别的数据点。 在SVM中&#xff0c;数据点…

【C++】类型转换 ⑤ ( 常量和非常量之间的类型转换 - 常量类型转换 const_cast | const 左数右指原则 | 代码示例 )

文章目录 一、const 关键字简介1、const 修饰普通数据2、const 修饰指针 ( 左数右指原则 | 指针常量 | 常量指针 ) 二、常量和非常量 之间的类型转换 - 常量类型转换 const_cast1、常量类型转换 const_cast2、常量不能直接修改3、修改常量值的方法4、特别注意 - 确保指针指向的…