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

锁策略总结

锁策略

悲观锁和乐观锁

乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度,这两个锁面对锁冲突的态度是相反的。

  • 乐观锁:认为不存在很多的并发操作,因此不需要加锁。
  • 悲观锁:认为存在很多并发操作,因此需要加锁。

重量级锁和轻量级锁

重量级锁和轻量级锁是通过结果去看待加锁解锁的过程开销。做的工作多消耗资源多,做的工作少消耗资源少。因此我们会认为乐观锁是轻量级锁,悲观锁是重量级锁。

  • 重量级锁:是进入内核态的加锁逻辑,资源开销较大。
  • 轻量级锁:是纯用户态的加锁逻辑,资源开销较小。  

自旋锁和挂起等待锁

  • 自旋锁:是一种轻量级锁,自旋锁类是一直反复查看当前锁是否就绪,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 的内容,下次放送。

相关文章:

锁策略总结

锁策略 悲观锁和乐观锁 乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度&#xff0c;这两个锁面对锁冲突的态度是相反的。 乐观锁&#xff1a;认为不存在很多的并发操作&#xff0c;因此不需要加锁。悲观锁&#xff1a;认为存在很多并发操作&#xff0c;因此需…...

蓝桥杯备考day2

1.1 map及其函数 map 提供一对一的数据处理能力&#xff0c;由于这个特性&#xff0c;它完成有可 能在我们处理一对一数据的时候&#xff0c;在编程上提供快速通道。map 中的第一 个值称为关键字(key)&#xff0c;每个关键字只能在 map 中出现一次&#xff0c;第二个称为该 关…...

Mac电脑安装蚁剑

1&#xff1a; github 下载源码和加载器&#xff1a;https://github.com/AntSwordProjectAntSwordProject GitHubAntSwordProject has 12 repositories available. Follow their code on GitHub.https://github.com/AntSwordProject 以该图为主页面&#xff1a;antSword为源码…...

品牌百度百科词条创建多少钱?

百度百科作为国内最具权威和影响力的知识型平台&#xff0c;吸引了无数品牌和企业争相入驻。一个品牌的百度百科词条&#xff0c;不仅是对品牌形象的一种提升&#xff0c;更是增加品牌曝光度、提高品牌知名度的重要途径。品牌百度百科词条创建多少钱&#xff0c;这成为了许多企…...

Linux安装及管理程序

目录 一.Linux应用程序基础 1.应用程序与系统命令的关系 2.典型应用程序的目录结构 3.常见的Linux软件包封装类型 二.RPM 软件包管理工具 1.RPM 软件包管理器 Red-Hat Package Manger 2.RPM软件包 3.RPM命令 三.源代码编译安装 1. yum 软件包管理器&#xff1a; 配…...

Mybatis generate xml 没有被覆盖

添加插件即可 <plugin type"org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>...

MercadoLibre(美客多)入仓预约系统操作流程-自动化约号(开篇)

目录 一、添加货件信息 二、输入货件信息 三、选择发货 四、填写交货日期 五、注意事项 MercadoLibre&#xff08;美客多&#xff09;于2021年10月18号上线了新预约入仓系统&#xff0c;在MercadoLibre美客多平台上&#xff0c;新入仓预约系统是一项非常重要的功能&#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 &#xff0c;java版本为17 2.sonar启动需要数据库,我先安装了mysql, 但是目前sonar从7.9开始不支持mysql&#xff0c;且java版本要最少11,推荐使用java17 3.安装postsql,创建sonar数据库 4.启…...

Git常用命令以及异常信息汇总

常用命令&#xff1a; 查看本地分支&#xff1a; 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&#xff0c;即符合REST&#xff08;Representational State Transfer&#xff0c;表述性状态转移&#xff09;架构风格的Web服务接口&#xff0c;已成为现代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语言基础---指针的基本语法

概述 内存地址 在计算机内存中&#xff0c;每个存储单元都有一个唯一的地址(内存编号)。通俗理解&#xff0c;内存就是房间&#xff0c;地址就是门牌号 指针和指针变量 指针&#xff08;Pointer&#xff09;是一种特殊的变量类型&#xff0c;它用于存储内存地址。指针的实…...

记录--病理切片图像处理

简介 数字病理切片&#xff0c;也称为全幻灯片成像&#xff08;Whole Slide Imaging&#xff0c;WSI&#xff09;或数字切片扫描&#xff0c;是将传统的玻片病理切片通过高分辨率扫描仪转换为数字图像的技术。这种技术对病理学领域具有革命性的意义&#xff0c;因为它允许病理…...

Android使用shape属性绘制边框内渐变色

目录 先上效果图实现方法shape属性介绍代码结果 先上效果图 这是使用AndroidStudio绘制的带有渐变色的边框背景色 实现方法 项目中由于UI设计需求&#xff0c;需要给按钮、控件设置带有背景色效果的。以下是UI效果图。 这里我们使用shape属性来绘制背景效果。 shape属性介…...

分类算法(数据挖掘)

目录 1. 逻辑回归&#xff08;Logistic Regression&#xff09; 2. 支持向量机&#xff08;Support Vector Machine, SVM&#xff09; 3. 决策树&#xff08;Decision Tree&#xff09; 4. 随机森林&#xff08;Random Forest&#xff09; 5. K近邻&#xff08;K-Nearest …...

scaling laws for neural language models

关于scaling law 的正确认识 - 知乎最近scaling law 成了最大的热词。一般的理解就是&#xff0c;想干大模型&#xff0c;清洗干净数据&#xff0c;然后把数据tokens量堆上来&#xff0c;然后搭建一个海量H100的集群&#xff0c;干就完了。训练模型不需要啥技巧&#xff0c;模型…...

水经微图IOS版5.2.0发布

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;简称“微图”&#xff09;IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规&#xff08;矩形、圆、椭圆、扇形&#xff09;绘制功能、地形夸张等主要功能。 当前版本 当前版本号为&#xff1a;5…...

聚观早报 | 哪吒L上市定档;iPhone 16最新高清渲染图

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月10日消息 哪吒L上市定档 iPhone 16最新渲染图 华为太空表与问界M9联动 蔚来万里长城加电风景线正式贯通 Red…...

【C++】手搓 list 容器

送给大家一句话&#xff1a; 若结局非你所愿&#xff0c;就在尘埃落定前奋力一搏。—— 《夏目友人帐》 手搓 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…...

3步掌握WeChatExporter:免费开源的微信数据备份解决方案

3步掌握WeChatExporter&#xff1a;免费开源的微信数据备份解决方案 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 微信聊天记录中蕴含着无数珍贵的工作沟通、个人回忆和…...

Motrix WebExtension终极指南:如何让你的浏览器下载速度提升300%

Motrix WebExtension终极指南&#xff1a;如何让你的浏览器下载速度提升300% 【免费下载链接】motrix-webextension A browser extension for the Motrix Download Manager and its forks 项目地址: https://gitcode.com/gh_mirrors/mo/motrix-webextension 你是否厌倦了…...

从STM32转战华大HC32F4A0:手把手教你搞定TIM6的PWM输入捕获(附中断配置避坑点)

从STM32到HC32F4A0的PWM输入捕获实战&#xff1a;TIM6配置与中断避坑指南 对于习惯了STM32生态的嵌入式开发者来说&#xff0c;初次接触华大半导体的HC32F4A0系列MCU时&#xff0c;往往会遇到一些意料之外的挑战。PWM输入捕获作为电机控制、频率测量等应用中的核心功能&#xf…...

Windows系统移植macOS光标主题:设计原理与安装实践

1. 项目概述&#xff1a;为Windows系统移植macOS光标主题如果你和我一样&#xff0c;长期在Windows和macOS双系统或双设备间切换工作&#xff0c;一定会对两者截然不同的光标设计有深刻的感受。macOS的光标以其简洁、圆润的线条和恰到好处的动画反馈&#xff0c;在视觉体验和操…...

告别CNN!用PyG Temporal和GC-LSTM搞定动态社交网络的好友推荐(附完整代码)

动态社交网络好友推荐的工程实践&#xff1a;基于GC-LSTM与PyG Temporal的完整解决方案 社交网络的动态特性为传统推荐系统带来了巨大挑战。当用户关系每分每秒都在变化时&#xff0c;静态的协同过滤或内容推荐方法往往显得力不从心。本文将分享如何利用PyG Temporal库和GC-LST…...

ARM中断控制器架构演进与Redistributor关键设计

1. ARM中断控制器架构演进与Redistributor定位现代多核处理器系统中&#xff0c;中断控制器作为连接外设与CPU的核心枢纽&#xff0c;其设计直接影响系统实时性和吞吐量。ARM架构从GICv2到GICv4的演进过程中&#xff0c;最显著的变革之一是引入了Redistributor模块。这个位于CP…...

Claude代码会话实战指南:从问答到结构化协作的效能提升

1. 项目概述&#xff1a;Claude Code Session 的实战效能提升指南最近在深度使用 Claude 进行代码开发时&#xff0c;我发现了一个宝藏仓库&#xff1a;mantra-hq/claude-code-session-tips。这并非一个可以直接运行的软件库&#xff0c;而是一份由社区高手们精心整理的、关于如…...

10个必备的Solidity安全技巧:Secureum-mind_map实践经验分享

10个必备的Solidity安全技巧&#xff1a;Secureum-mind_map实践经验分享 【免费下载链接】secureum-mind_map Central Repository for the Epoch 0 coursework and quizzes. Contains all the content, cross-referenced and linked. 项目地址: https://gitcode.com/gh_mirr…...

构建数据科学AI代理规则库:从自动化到智能化的关键路径

1. 项目概述&#xff1a;一个为数据科学工作流定制的智能代理规则库最近在GitHub上看到一个挺有意思的项目&#xff0c;叫ds-agent-rules。光看名字&#xff0c;你可能觉得这又是一个平平无奇的规则文件集合。但作为一个在数据科学和自动化领域摸爬滚打多年的从业者&#xff0c…...

从Arduino官网的‘eagle-files’说起:给硬件新手的Autodesk Eagle PCB设计入门指南

从Eagle文件到PCB设计&#xff1a;开源硬件爱好者的实战入门指南 在开源硬件社区里&#xff0c;Arduino项目的"eagle-files"文件夹常常让新手感到困惑又好奇。这些文件背后隐藏着一个强大的工具链——Autodesk Eagle&#xff0c;它是欧美开源硬件生态中PCB设计的通用…...