锁策略总结
锁策略
悲观锁和乐观锁
乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度,这两个锁面对锁冲突的态度是相反的。
- 乐观锁:认为不存在很多的并发操作,因此不需要加锁。
- 悲观锁:认为存在很多并发操作,因此需要加锁。
重量级锁和轻量级锁
重量级锁和轻量级锁是通过结果去看待加锁解锁的过程开销。做的工作多消耗资源多,做的工作少消耗资源少。因此我们会认为乐观锁是轻量级锁,悲观锁是重量级锁。
- 重量级锁:是进入内核态的加锁逻辑,资源开销较大。
- 轻量级锁:是纯用户态的加锁逻辑,资源开销较小。
自旋锁和挂起等待锁
- 自旋锁:是一种轻量级锁,自旋锁类是一直反复查看当前锁是否就绪,CPU不停空转会消耗大量地CPU。
- 挂起等待锁:是一种重量级锁,该锁不会像自旋锁一样一直查看锁状态而是先去做别的事情,过一会再来看当前锁是否就绪。
互斥锁和读写锁
- 互斥锁:当两个线程竞争同一把锁时会产生锁冲突进而阻塞等待。
- 读写锁:根据代码实际的逻辑进行加锁,有读锁和写锁两种锁。读锁和读锁之间不会产生锁竞争;读锁和写锁之间会产生锁竞争;写锁和写锁之间,会产生锁竞争。如果代码中读的场景多写的场景少时,读写锁相比于互斥锁优化了效率、减少了不必要的锁竞争。
可重入锁和不可重入锁
- 不可重入锁:是指同一个线程对同一把锁连续加锁两次,产生了死锁。
- 可重入锁:是指同一个线程在外层方法获取锁,进入内层方法会自动获取锁。
注ReentrantLock和Synchronized都是可重入锁。
公平锁和非公平锁
- 公平是指遵循先来后到的原则的,因此遵守先来后到就是公平锁,不遵守先来后到的就是非公平锁。
- 例:t1,t2,t3三个线程竞争同一把锁,谁先来的谁就拿到锁的情况叫公平锁。如果三个线程随机一个拿到锁,后来的线程可能会先拿到锁的情况叫非公平锁。
- 公平锁:指多个线程按照申请锁的顺序来获取锁。
- 非公平锁:指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。
操作系统默认的锁的调度是非公平的。系统对于线程的调度是随机的,自带的synchronized这个锁是非公平的。想要实现公平锁需要在synchronized的基础上,加个队列来记录这些加锁线程的顺序。
cas 和 synchronized 优化过程
CAS全称: compare and swap. 根据字面意思理解为"比较并交换"
一个CAS涉及到以下操作:
假设内存中的原数据是V,旧的预期值是A,需要修改的新值是B
1).先比较A和V是否相等(比较)
2).如果比较相等,就将B写入V(交换)
3).返回操作是否成功
在上述交换过程中,大多数情况下并不关心B后续的情况,更关心的是V这个变量的情况
这里说是交换,其实可以近似理解成:赋值
此处最特别的地方是:上述这个CAS过程并非是通过一段代码实现的,而是通过一条CPU指令完成的,这说明CAS操作是原子的!!!!!
CAS可以理解成是CPU提供的一个特殊指令,通过这个指令可以一定程度上处理线程安全问题.
CAS的伪代码:
boolean CAS(value, oldValue, swapValue) {if (value == oldValue) {value = swapValue;return true;}return false;
}
CAS的应用场景
CAS的应用场景主要有两个:
1).实现原子类
java标准库提供了java.util.concurrent.atomic包,里面的类都是基于CAS的方式实现的,其中最典型的就是AtomicInteger类,其中的getAndIncrement相当于i++操作
通过下面一个练习来理解原子类:
两个线程增加同一个变量
public class Exercise {public static void main(String[] args) throws InterruptedException {AtomicInteger integer = new AtomicInteger(0);Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {integer.getAndIncrement();// 相当于i++操作}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {integer.getAndIncrement();// 相当于i++操作}});t1.start();t2.start();// 为了让主线程等待t1线程和t2线程执行完毕t1.join();t2.join();System.out.println(integer);} }实现自旋锁
通过下面的伪代码理解:
public class SpinLock { private Thread owner = null; public void lock(){// 通过 CAS 看当前锁是否被某个线程持有. // 如果这个锁已经被别的线程持有, 那么就自旋等待. // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程. while(!CAS(this.owner, null, Thread.currentThread())){}}public void unlock (){this.owner = null;} }ABA问题
CAS运行的核心:检查value与oldValue是否一致.如果一致,就视为value中途没有被修改过,所以进行下一步交换操作是没问题的.
但是,这里的一致,可能是value没有被修改过,也有可能是value被修改过又改回来了.
把value的值设为A的话,CAS判定value为A,此时value的值可能始终为A,也可能是value本来是A,被修改为了B,最后又还原成了A.
这就是CAS的典型问题:ABA问题
假设 张三 有 100 存款 . 张三 想从 ATM 取 50 块钱 . 取款机创建了两个线程 , 并发的来执行 -50
操作 .
我们期望一个线程执行 -50 成功 , 另一个线程 -50 失败 .
如果使用 CAS 的方式来完成这个扣款过程就可能出现问题 .
正常的过程
1) 存款 100. 线程 1 获取到当前存款值为 100, 期望更新为 50; 线程 2 获取到当前存款值为 100, 期
望更新为 50.
2) 线程 1 执行扣款成功 , 存款被改成 50. 线程 2 阻塞等待中 .
3) 轮到线程 2 执行了 , 发现当前存款为 50, 和之前读到的 100 不相同 , 执行失败 .
异常的过程
1) 存款 100. 线程 1 获取到当前存款值为 100, 期望更新为 50; 线程 2 获取到当前存款值为 100, 期
望更新为 50.
2) 线程 1 执行扣款成功 , 存款被改成 50. 线程 2 阻塞等待中 .
3) 在线程 2 执行之前 ,张三 的朋友正好给张三转账 50, 账户余额变成 100 !!
4) 轮到线程 2 执行了 , 发现当前存款为 100, 和之前读到的 100 相同 , 再次执行扣款操作
这个时候 , 扣款操作被执行了两次 !!!
解决ABA问题的方法:给要修改的值,引入版本号
在 CAS 比较数据当前值和旧值的同时 , 也要比较版本号是否符合预期 .
CAS 操作在读取旧值的同时 , 也要读取版本号 .
真正修改的时候:
如果当前版本号和读到的版本号相同 , 则修改数据 , 并把版本号 + 1.
如果当前版本号高于读到的版本号 . 就操作失败 ( 认为数据已经被修改过了 ).
引入版本号后,解决刚才转账异常的情况:
假设 张三 有 100 存款 . 张三 想从 ATM 取 50 块钱 . 取款机创建了两个线程 , 并发的来执行 -50
操作 .
我们期望一个线程执行 -50 成功 , 另一个线程 -50 失败 .
为了解决 ABA 问题 , 给余额搭配一个版本号 , 初始设为 1.
1) 存款 100. 线程 1 获取到 存款值为 100, 版本号为 1, 期望更新为 50; 线程 2 获取到存款值为 100,
版本号为 1, 期望更新为 50.
2) 线程 1 执行扣款成功 , 存款被改成 50, 版本号改为 2. 线程 2 阻塞等待中 .
3) 在线程 2 执行之前 , 张三 的朋友正好给滑稽转账 50, 账户余额变成 100, 版本号变成 3.
4) 轮到线程 2 执行了 , 发现当前存款为 100, 和之前读到的 100 相同 , 但是当前版本号为 3, 之前读
到的版本号为 1, 版本小于当前版本 , 认为操作失败 .
Synchronized
1).synchronized既是一个悲观锁,也是一个乐观锁
synchronized默认是乐观锁,但是如果发现锁竞争激烈,就会变成悲观锁
2).synchronized既是一个轻量级锁,也是一个重量级锁
synchronized默认是轻量级锁,但是如果发现锁竞争激烈,就会变成重量级锁
3).synchronized这里的轻量级锁,是基于自旋锁的方式实现的.
synchronized这里的重量级锁,是基于挂起等待锁的方式实现的.
4).synchronized 不是读写锁
5).synchronized 是非公平锁
6).synchronized 是可重入锁
jvm将synchronized 锁分为:无锁 偏向锁 轻量级锁 重量级锁 状态,会根据情况,进行依次升级.
1).偏向锁
第一个尝试加锁的线程,优先进入偏向锁状态.偏向锁不是真的"加锁",而是做个偏向锁标记,记录这个锁属于哪个线程.
如果整个使用锁的过程中,没有出现锁竞争,在synchronized执行完之后,取消偏向锁即可
如果整个使用锁的过程中.另一个线程也尝试加锁,那么在它加锁之前,迅速的把偏向锁状态升级为加锁状态,另一个线程只能阻塞等待了.
2).轻量级锁
随着其它线程进入竞争,偏向锁状态被消除,进入轻量级锁状态(自适应的自旋锁)
此处的轻量级锁就是通过CAS来实现的.
自旋操作是一直让CPU空转,比较浪费CPU资源,因此,此处的自旋不会一直持续进行,而是达到一定的时间/重试次数,就不在自旋了,也就是所谓的"自适应".
3).重量级锁
如果竞争进一步激烈,自旋不能快速获取到锁,就会升级为重量级锁
此处的重量级锁就是指用到内核提供的mutex
之后还有关于Synchronized 的内容,下次放送。
相关文章:
锁策略总结
锁策略 悲观锁和乐观锁 乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度,这两个锁面对锁冲突的态度是相反的。 乐观锁:认为不存在很多的并发操作,因此不需要加锁。悲观锁:认为存在很多并发操作,因此需…...
蓝桥杯备考day2
1.1 map及其函数 map 提供一对一的数据处理能力,由于这个特性,它完成有可 能在我们处理一对一数据的时候,在编程上提供快速通道。map 中的第一 个值称为关键字(key),每个关键字只能在 map 中出现一次,第二个称为该 关…...
Mac电脑安装蚁剑
1: github 下载源码和加载器:https://github.com/AntSwordProjectAntSwordProject GitHubAntSwordProject has 12 repositories available. Follow their code on GitHub.https://github.com/AntSwordProject 以该图为主页面:antSword为源码…...
品牌百度百科词条创建多少钱?
百度百科作为国内最具权威和影响力的知识型平台,吸引了无数品牌和企业争相入驻。一个品牌的百度百科词条,不仅是对品牌形象的一种提升,更是增加品牌曝光度、提高品牌知名度的重要途径。品牌百度百科词条创建多少钱,这成为了许多企…...
Linux安装及管理程序
目录 一.Linux应用程序基础 1.应用程序与系统命令的关系 2.典型应用程序的目录结构 3.常见的Linux软件包封装类型 二.RPM 软件包管理工具 1.RPM 软件包管理器 Red-Hat Package Manger 2.RPM软件包 3.RPM命令 三.源代码编译安装 1. yum 软件包管理器: 配…...
Mybatis generate xml 没有被覆盖
添加插件即可 <plugin type"org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>...
MercadoLibre(美客多)入仓预约系统操作流程-自动化约号(开篇)
目录 一、添加货件信息 二、输入货件信息 三、选择发货 四、填写交货日期 五、注意事项 MercadoLibre(美客多)于2021年10月18号上线了新预约入仓系统,在MercadoLibre美客多平台上,新入仓预约系统是一项非常重要的功能&#x…...
Unity TextMeshProUGUI 获取文本尺寸·大小
一般使用ContentSizeFitter组件自动变更大小 API 渲染前 Vector2 GetPreferredValues(string text)Vector2 GetPreferredValues(string text, float width, float height)Vector2 GetPreferredValues(float width, float height) 渲染后 Vector2 GetRenderedValues()Vector…...
Sonar下启动发生错误,elasticsearch启动错误
Download | SonarQube | Sonar (sonarsource.com) 1.首先我的sonar版本为 10.4.1 ,java版本为17 2.sonar启动需要数据库,我先安装了mysql, 但是目前sonar从7.9开始不支持mysql,且java版本要最少11,推荐使用java17 3.安装postsql,创建sonar数据库 4.启…...
Git常用命令以及异常信息汇总
常用命令: 查看本地分支: git branch 创建一个新仓库 git clone 仓库地址xxxxx cd 目标目录 git switch -c main touch README.md git add README.md git commit -m "add README" git push -u origin main 推送现有文件夹 cd 目标目录 git in…...
解释Python中的RESTful API设计和实现
解释Python中的RESTful API设计和实现 RESTful API,即符合REST(Representational State Transfer,表述性状态转移)架构风格的Web服务接口,已成为现代Web应用程序通信的标准。Python作为一种灵活且强大的编程语言&…...
一、Nginx部署
Nginx部署 一、Docker部署1.复制Nginx配置文件2.启动Nginx容器 一、Docker部署 1.复制Nginx配置文件 # 1.拉取镜像 docker pull nginx # 2.启动nginx容器 docker run --restartalways --namenginx -p 80:80 -d nginx # 3.宿主机创建挂载目录 mkdir /root/docker/nginx -p # 4…...
C语言基础---指针的基本语法
概述 内存地址 在计算机内存中,每个存储单元都有一个唯一的地址(内存编号)。通俗理解,内存就是房间,地址就是门牌号 指针和指针变量 指针(Pointer)是一种特殊的变量类型,它用于存储内存地址。指针的实…...
记录--病理切片图像处理
简介 数字病理切片,也称为全幻灯片成像(Whole Slide Imaging,WSI)或数字切片扫描,是将传统的玻片病理切片通过高分辨率扫描仪转换为数字图像的技术。这种技术对病理学领域具有革命性的意义,因为它允许病理…...
Android使用shape属性绘制边框内渐变色
目录 先上效果图实现方法shape属性介绍代码结果 先上效果图 这是使用AndroidStudio绘制的带有渐变色的边框背景色 实现方法 项目中由于UI设计需求,需要给按钮、控件设置带有背景色效果的。以下是UI效果图。 这里我们使用shape属性来绘制背景效果。 shape属性介…...
分类算法(数据挖掘)
目录 1. 逻辑回归(Logistic Regression) 2. 支持向量机(Support Vector Machine, SVM) 3. 决策树(Decision Tree) 4. 随机森林(Random Forest) 5. K近邻(K-Nearest …...
scaling laws for neural language models
关于scaling law 的正确认识 - 知乎最近scaling law 成了最大的热词。一般的理解就是,想干大模型,清洗干净数据,然后把数据tokens量堆上来,然后搭建一个海量H100的集群,干就完了。训练模型不需要啥技巧,模型…...
水经微图IOS版5.2.0发布
随时随地,微图一下! 水经微图(简称“微图”)IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规(矩形、圆、椭圆、扇形)绘制功能、地形夸张等主要功能。 当前版本 当前版本号为:5…...
聚观早报 | 哪吒L上市定档;iPhone 16最新高清渲染图
聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 4月10日消息 哪吒L上市定档 iPhone 16最新渲染图 华为太空表与问界M9联动 蔚来万里长城加电风景线正式贯通 Red…...
【C++】手搓 list 容器
送给大家一句话: 若结局非你所愿,就在尘埃落定前奋力一搏。—— 《夏目友人帐》 手搓 list 容器 1 前言1.1 底层结构1.2 使用场景1.3 功能简介 2 框架搭建2.1 节点类2.2 list 类2.3 迭代器类 3 功能实现3.1 begin() 与 end()3.2 插入操作3.3 删除操作3…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...


