Java Web 实战 11 - 多线程进阶之常见的锁策略
常见的锁策略
- 常见的锁策略
- 1. 乐观锁 VS 悲观锁
- 2. 普通的互斥锁 VS 读写锁
- 3. 重量级锁 VS 轻量级锁
- 4. 自旋锁 VS 挂起等待锁
- 5. 公平锁 VS 非公平锁
- 6. 可重入锁 vs 不可重入锁
- 7. 常见面试题
大家好 , 这篇文章给大家带来的是多线程中常见的锁策略 , 我们会给大家讲解 6 种类别的锁
- 乐观锁 VS 悲观锁
- 普通的互斥锁 VS 读写锁
- 重量级锁 VS 轻量级锁
- 自旋锁 VS 挂起等待锁
- 公平锁 VS 非公平锁
- 可重入锁 vs 不可重入锁
- 常见面试题
针对常见的锁策略 , 这就属于面试爱考但是工作用不上的内容了
大家理解记忆即可
推荐大家跳转到这观看效果更佳
上一篇文章的链接我也给大家贴到这里了小狗说要请大家喝饮料 , 快跟我说 : “谢谢小狗”
常见的锁策略
锁策略指的是 : 加锁的时候我们咋加的
这里说的锁策略 , 和语言基本无关 , 其他的语言也涉及到 “锁策略”
1. 乐观锁 VS 悲观锁
乐观锁 : 预测接下来锁冲突的概率不大 , 就需要做一类操作
悲观锁 : 预测接下来锁冲突的概率很大, 就需要做另一类操作
举个栗子 :
疫情导致封校了
有的人就比较紧张 , 去超市抓紧屯点零食 -> 乐观锁
有的人就无所谓 , 饿不死就行 -> 悲观锁
针对预测的结果不同 , 解决的方法不同
乐观锁相对来说 , 成本更小 ; 悲观锁相对来说 , 成本更大
我们之前介绍过 synchronized , 它既是悲观锁 , 又是乐观锁 , 也就是自适应锁
当前锁冲突概率不大 , 以乐观锁的方式运行 , 往往是纯用户态执行的
一旦发现锁冲突大了 , 以悲观锁的方式运行 , 往往要进入内核 , 对当前线程进行挂起等待
2. 普通的互斥锁 VS 读写锁
synchronized 就是普通的互斥锁 , 两个加锁操作会产生竞争
读写锁把加锁操作进行细化了 , 分成了 “加读锁” 和 “加写锁”
情况1 :
线程 A 尝试加写锁
线程 B 尝试加写锁
线程 A 和 线程 B 产生竞争 , 和普通的锁没啥区别
情况 2 :
线程 A 尝试加读锁
线程 B 尝试加读锁
线程 A 和 线程 B 不产生竞争 , 锁相当于没加一样
(多线程读 , 不涉及修改 , 是线程安全的)
情况 3 :
线程 A 尝试加读锁
线程 B 尝试加写锁
线程 A 和线程 B 产生竞争 , 和普通的锁没什么区别
只有情况 2 (两个线程都是加读锁) 是线程安全的
读写锁就是把读操作和写操作区分对待 , Java 标准库提供了 ReentrantReadWriteLock
类 , 实现了读写
锁.
ReentrantReadWriteLock.ReadLock
类表示一个读锁 . 这个对象提供了lock / unlock
方法进行加锁解锁 .ReentrantReadWriteLock.WriteLock
类表示一个写锁 . 这个对象也提供了lock / unlock
方法进行加锁解锁 .
3. 重量级锁 VS 轻量级锁
重量级锁指的是锁的开销比较大 , 做的工作比较多
轻量级锁指的是锁的开销比较小 , 做的工作比较少
悲观锁 , 经常会是重量级锁
乐观锁 , 经常会是轻量级锁
但是不是绝对的
那什么叫做 做的工作多 , 做的工作少呢 ?
我们一般认为 , 锁这个东西要保持互斥的 , 那保持互斥要有力量来源的
我们 Java 中实现一把锁 , 需要使用 synchronized 关键字 (后续还会降解 ReentrantLock)
那 Java 里面实现锁 , 主要是 JVM 提供的 synchronized 和 ReentrantLock 这两个机制
那 JVM 之所以能够实现锁机制 , 是因为操作系统提供了 mutex 互斥锁
操作系统之所以能够加锁 , 是因为 CPU 提供了一些用来加锁的 , 能够保证原子操作的指令
重量级锁主要是依赖了操作系统提供的锁 , 使用操作系统提供的锁 , 就很容易产生阻塞等待
轻量级锁主要是尽量的避免使用操作系统提供的锁 , 尽量在用户态完成功能 , 也就是尽量的避免用户态和内核态的切换 , 尽量避免挂起等待 (阻塞等待)
synchronized 是自适应锁 , 既是轻量级锁 , 又是重量级锁
也是根据锁冲突的情况来决定的
冲突的不高就是轻量级锁 , 冲突的很高就是重量级锁
4. 自旋锁 VS 挂起等待锁
自旋锁和挂起等待锁是更加深入来看的 , 相当于分析的最内层
自旋锁 : 当我们发现锁冲突的时候 , 不会挂起等待 , 它会迅速再次尝试这个锁能不能获取到 (超级舔狗)
他就相当于是一个 while 循环一直获取锁的状态
一旦锁被释放 , 就可以第一时间获取到
如果锁一直不释放 , 就会消耗大量的 CPU
自旋锁是更加轻量的 , 效率更高的
挂起等待锁 : 发现锁冲突 , 就挂起等待
一旦锁被释放 , 不能第一时间获取到
在锁被其他线程占用的时候 , 会放弃 CPU 资源
挂起等待锁是更加重量的 , 效率更低的
自旋锁 , 是轻量级锁的具体实现
挂起等待锁 , 是重量级锁的具体实现
自旋锁是轻量级锁 , 也是乐观锁
挂起等待锁是重量级锁 , 也是悲观锁
synchronized 作为轻量级锁的时候 , 内部是自旋锁
synchronized 作为重量级锁的时候 , 内部是挂起等待锁
5. 公平锁 VS 非公平锁
啥样的情况才算是公平呢 ?
符合 “先来后到” 这样的规则 , 就是公平
先来的 , 先排在前面 . 来晚的 , 就在后面排着
举个栗子 :
操作系统中 , 默认的锁的竞争规则 , 就是非公平的 , 没有考虑先来后到
如果要想使用公平锁 , 就需要使用额外的数据结构来进行控制实现
所以 synchronized 是非公平锁
6. 可重入锁 vs 不可重入锁
7. 常见面试题
- 你是怎么理解乐观锁和悲观锁的,具体怎么实现呢?
悲观锁认为多个线程访问同一个共享变量冲突的概率较大, 会在每次访问共享变量之前都去真正加锁.
乐观锁认为多个线程访问同一个共享变量冲突的概率不大. 并不会真的加锁, 而是直接尝试访问数据. 在访问的同时识别当前的数据是否出现访问冲突.
悲观锁的实现就是先加锁(比如借助操作系统提供的 mutex), 获取到锁再操作数据. 获取不到锁就等待.
乐观锁的实现可以引入一个版本号. 借助版本号识别出当前的数据访问是否冲突. (实现细节参考上面的图).
- 介绍下读写锁?
读写锁就是把读操作和写操作分别进行加锁.
读锁和读锁之间不互斥.
写锁和写锁之间互斥.
写锁和读锁之间互斥.
读写锁最主要用在 “频繁读, 不频繁写” 的场景中.
- 什么是自旋锁,为什么要使用自旋锁策略呢,缺点是什么?
如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁.
相比于挂起等待锁,
优点: 没有放弃 CPU 资源, 一旦锁被释放就能第一时间获取到锁, 更高效. 在锁持有时间比较短的场景下非常有用.
缺点: 如果锁的持有时间较长, 就会浪费 CPU 资源.
- synchronized 是可重入锁么?
是可重入锁.
可重入锁指的就是连续两次加锁不会导致死锁.
实现的方式是在锁中记录该锁持有的线程身份, 以及一个计数器(记录加锁次数). 如果发现当前加锁的线程就是持有锁的线程, 则直接计数自增.
到这里本篇文章就结束了
如果有帮助的话请一键三连~
小狗会请你喝饮料的
相关文章:

Java Web 实战 11 - 多线程进阶之常见的锁策略
常见的锁策略常见的锁策略1. 乐观锁 VS 悲观锁2. 普通的互斥锁 VS 读写锁3. 重量级锁 VS 轻量级锁4. 自旋锁 VS 挂起等待锁5. 公平锁 VS 非公平锁6. 可重入锁 vs 不可重入锁7. 常见面试题大家好 , 这篇文章给大家带来的是多线程中常见的锁策略 , 我们会给大家讲解 6 种类别的锁…...

(20)目标检测算法之YOLOv5计算预选框、详解anchor计算
目标检测算法之YOLOv5计算预选框、详解anchor计算 单节段目标检测算法中:预选框的设定直接影响最终的检测精度众所周知,yolov5中采用自适应调整预选框anchor的大小,但万事开头难,配置文件config中的预设还是很重要yolo算法作为on…...

3-1 SpringCloud快速开发入门: Ribbon 是什么
接上一章节Eureka 服务注册中心自我保护机制,这里讲讲Ribbon 是什么 Ribbon 是什么 通常说的负载均衡是指将一个请求均匀地分摊到不同的节点单元上执行,负载均和分为硬件负载均衡和软件负载均衡: **硬件负载均衡:**比如 F5、深信…...

Java【lambda表达式】语法及使用方式介绍
相关文章目录 第一篇: Java【EE初阶】进程相关知识 进程管理 内存管理 文章目录相关文章目录前言一、lambda表达式 是什么?1, lambda表达式 的背景2, 什么是 函数式接口3, lambda表达式 的语法二、lambda表达式 的使用方式1, 无参无返回值2, 有一个参…...

【AcWing】蓝桥杯备赛-深度优先搜索-dfs(2)
目录 写在前面: 题目:94. 递归实现排列型枚举 - AcWing题库 读题: 输入格式: 输出格式: 数据范围: 输入样例: 输出样例: 解题思路: 代码: AC &…...

‘conda‘不是内部或外部命令,也不是可运行的程序或批处理文件。
Anaconda环境搭建常见问题 conda不是内部或外部命令,也不是可运行的程序或批处理文件。 解决方案:配置环境变量 1.找到Anaconda Nvaigator单机右键 2.更多 3.打开文件所在位置 4.继续Anaconda Nvaigator单机右键,更多,选择文件…...

HTTP 3.0来了,UDP取代TCP成为基础协议,TCP究竟输在哪里?
TCP 是 Internet 上使用和部署最广泛的协议之一,多年来一直被视为网络基石,随着HTTP/3正式被标准化,QUIC协议成功“上位”,UDP“取代”TCP成为基础协议,TCP究竟“输”在哪里? HTTP/3 采用了谷歌多年探索的基…...
《JavaCV从入门到实战教程合集》介绍和目录
前言 《JavaCV从入门到实战教程合集》是2016年《JavaCV开发实战教程》和2018年《JavaCV入门教程》2022年《JavaCV音视频实战宝典》三合一汇总合集,完整包含JavaCV入门教程》、《JavaCV开发实战教程》系列和《JavaCV音视频实战宝典》系列所有付费内容。 《JavaCV入…...

Form Generator扩展 文本 组件
一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…...

【C/C++】必知必会知识点大总结
✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📚专栏地址:C/C知识点 📣专栏定位:整理一下 C 相关的知识点,供大家学习参考~ ❤️如果有收获的话,欢迎点赞👍…...

【JavaScript 逆向】百度旋转验证码逆向分析
声明本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!案例目标爱企查百度安全验证百度搜索:aHR0cHM6Ly93YXBwYXNzLmJhaWR1LmNvbS9zdGF0aWMvY2FwdGNoYS8以上均做了脱敏处理,B…...
PCL 点云投影到直线(C++详细过程版)
目录 一、算法原理二、代码实现三、结果展示1、原始点云2、投影结果一、算法原理 直线方程有三种表示法:一般式、点向式、参数式。PCL中统一采用的是点向式,直线的点向式方程为: x − x 0 m = y −...

中缀表达式转后缀表示式,及后缀表达式的运算规则
后缀表达式又称为逆波兰表达式 一,中缀表达式如何转后缀表达式 假定给出以下中缀表达式 132*2-1; 要将该表达式转为后缀表达式,我们要按照一定的规则去走,并且用到栈。 先来看规则中缀转后缀的规则: 前提&#x…...
【C++】STL简介
文章目录什么是STLSTL版本 原始版本(HP版本) P.J.版本 RW版本 SGI版本STL六大组件 容器 算法 仿函数 空间配置器 迭代器 配接器STL缺陷什么是STL STL(standard template libaray-标准模板库):是C标准库的重要组成部分,不…...
(小甲鱼python)文件永久存储(上)总结 python文件永久存储(创建打开文件、文件对象的各种方法及含义)
一、文件永久存储 如何将数据永久的存放在硬盘上,具体如下。 1.打开文件 定义:往大了讲计算机系统中由操作系统管理的具有名称的存储区域,往小了讲是生活中的PPT、Excel、word三剑客、视频文件、音频文件等。 创建打开文件: open…...
甲酸溶液除钠离子,丙酸溶液除钾离子,医药液体除钾
水是医药行业中用量大、使用 泛的一种原料,它在生产过程中和药剂药品的制备中发挥着极其重要的作用。制药用水的原水通常为自来水或深井水,原水不能直接用作制剂用水或实验用水。因为原水中含有各类盐类和化合物,溶有CO2,还存在大…...

操作系统(2.2)--进程的描述与控制
目录 二、进程的描述 1.进程的定义和特征 1.1进程的定义 1.2进程的特征 2.进程的基本状态及转换 2.1进程的三种基本状态 2.2 三种基本状态的转换 2.3创建状态和中止状态 3.挂起操作和进程状态的转换 3.1 挂起状态的引入 3.2 引入挂起操作后三个进程状态的转换 …...
Python连接es笔记四之创建和删除操作
这一篇笔记介绍一下索引和数据的创建和删除。 其实对于索引来说,如果可以接触到 kibana 的话,可以很方便的在界面进行操作,这里简单介绍一下如何使用代码来操作索引的创建和删除。 索引的创建和删除操作 使用的还是 es 的连接:…...
字符串填充到指定长度
一、需求 在传输一个文件的时候,传输的是二进制数据,整个数据文件的结构为: 文件名称 文件本身 其中文件名称固定占30个byte,存在的情况就是,有的文件名比较长,有的文件名比较短,所有要补足30…...

macOS虚拟机安装全过程(VMware)
作为一名忠实果粉,我最大的愿望就是能够拥有一台Macbook,体验macOS,但是作为学生党,这价钱,贵到离谱啊~~~ 不过,VMware这个神器,可以解决一切问题:既然macOS可以在Macbook上运行&…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...