多线程--常见锁策略--Java

目录

一、悲观锁VS乐观锁

1.悲观锁

2.乐观锁

二、重量级锁VS轻量级锁

1.重量级锁

2.轻量级锁

三、自旋锁

1.自旋锁概念

四、公平锁VS非公平锁

1.公平锁

2.非公平锁

3.注意

五、可重入锁和不可重入锁

六、读写锁

1.线程对于数据的访问方式


注意:以下讲解的锁策略不止局限于Java,任何和“锁”有关的话题都会牵扯到以下的内容,这些特性主要是给锁的设计者来参考的。

普通的程序员也需要了解一下,这对合理的使用锁有很大的帮助。

一、悲观锁VS乐观锁

1.悲观锁

总是假设最坏的情况,也就是每次拿到数据都会认为这个数据会被别人拿到修改,所以在每次拿到数据都会加上锁,这样别人想要获取数据就会阻塞直到它拿到锁。

2.乐观锁

假设数据一般情况下不会产生并发冲突,所以在数据提交更新的时候才会对数据是否会产生并发冲突进行判断,如果发现并发冲突就会给返回一个用户错误信息,让用户来决定怎么做。

举例来说:同学A和同学B向老师请教问题。

同学A认为老师是很忙的,去问问题老师大概率在忙不能帮他解决问题,所以他先给老师发信息问“老师您有空吗?我可以问个问题吗?”(相当于加锁操作)得到肯定的答复后,他才会真的去向老师问问题,得到否定的答复后,他会再等一段时间等到老师空闲的时候问问题,这个就是悲观锁。

同学B认为老师是比较闲的,去问问题老师大概率是有时间解答的,所以他直接去找老师(没加锁,直接访问资源)如果老师比较闲,问题直接就解决了,如果老师正好在忙,那么他也不会打扰老师,下次再来(虽然没加锁,但是能识别出数据访问冲突),这个就是乐观锁。

这两种思路并不能说谁优谁劣,要看当前场景适合哪种锁。

我们Java的Synchronized初始情况下是乐观锁,在运行过程中发现锁竞争频繁后会自动转为悲观锁。

就好⽐同学 C 开始认为 "⽼师⽐较闲的", 问问题都会直接去找⽼师. 但是直接来找两次⽼师之后, 发现⽼师都挺忙的, 于是下次再来问问题, 就先发个消息问问⽼师忙不忙, 再决定是否来问问题。

二、重量级锁VS轻量级锁

首先我们要明白锁的核心特性“原子性”这样的机制追根溯源可以追溯到CPU这样的硬件设备提供。

CPU提供了“原子性操作”。

操作系统通过CPU的原子指令实现了mutex互斥锁

JVM基于操作系统提供的互斥锁,实现了Synchronized 和ReentrantLock等关键字和子类。

1.重量级锁

加锁机制重度依赖OS提供的mutex。

大量的内核态用户态切换;很容易引发线程调度。

这两个操作的成本都很高,一旦引发了内核态和用户态的切换就意味着“沧海桑田”。

2.轻量级锁

加锁机制尽可能不使用OS提供的mutex,尽量在用户态代码完成,实在不行了在使用mutex。

少量的内核态用户态切换;不容易引发线程调度。

synchronized 开始是⼀个轻量级锁. 如果锁冲突⽐较严重, 就会变成重量级锁

三、自旋锁

按之前的方式,线程在抢锁失败后就会进入阻塞状态,放弃CPU,下次再次调用该线程就不知道是什么时候了。实际上,在线程抢锁失败后用不了多长时间,锁就会被释放,没必要放弃CPU,这时我们就可以使用自旋锁来解决这样的问题。

1.自旋锁概念

综上所述,在一个线程抢锁失败后,它会立即再次尝试获取锁,无限循环,这样在该锁释放的时候它能够立刻获取到锁。

自旋锁是一种典型的轻量级锁的实现方式:

优点:没有放弃CPU,不涉及线程的调度和阻塞,能够第一时间获取到锁。

缺点:如果锁被其他线程获取的时间比较长,就会持续不断的消耗CPU资源(挂起等待是不需要消耗CPU资源的)

Synchronized中的轻量锁策略大概率就是通过自旋锁的方式实现的。

四、公平锁VS非公平锁

假设有ABC三个线程,A线程先获取到锁,B线程尝试获取锁失败阻塞等待,C线程再尝试获取锁失败阻塞等待,那么当A线程释放锁后哪个线程获取到锁呢?

1.公平锁

遵守先来后到的规则,B线程比C线程更早尝试获取锁,所以B线程获取到锁。

2.非公平锁

不遵守先来后到的规则,BC两个线程都有可能获取到锁。

这就好比一群男生追一个女生,当女生和前任分手后,她挑选了追她最久的做男朋友这就是“公平锁”,如果她随机挑了一个她看着顺眼的这就是“非公平锁”。

3.注意

操作系统中线程的调度时随机的,如果不做任何限制的话,那么锁就是非公平锁,如果要实现公平锁需要用额外的数据结构来记录每个线程尝试获取锁的时间来实现公平锁。

公平锁和非公平锁直接没用优劣之分,具体看使用场景。

Synchronized实现的是非公平锁。

五、可重入锁和不可重入锁

可重入锁可以根据字面意思来理解,就是可以重复进入的锁,也就是说一个线程可以重复获取统一把锁,

⽐如⼀个递归函数⾥有加锁操作,递归过程中这个锁会阻塞⾃⼰吗?如果不会,那么这个锁就是可重 ⼊锁(因为这个原因可重⼊锁也叫做递归锁)。
Java⾥只要以Reentrant开头命名的锁都是可重⼊锁,⽽且JDK提供的所有现成的Lock实现类,包括 synchronized关键字锁都是可重⼊的。
⽽ Linux 系统提供的 mutex 是不可重⼊锁。
不可重入锁也就是一个线程重复获取同一把锁会产生“死锁问题”,也就是同一个线程内产生了阻塞,导致程序崩溃。

六、读写锁

多线程之间,数据的读取方之间不需要进行互斥,数据的写入方之间和写入方和读取方之间需要进行互斥。如果这几种场景下使用同一种锁就会产生极大的性能消耗,因此有了读写锁的产生。

1.线程对于数据的访问方式

一个线程对于数据的访问方式无非两种,读数据和写数据:

两个线程都是读一个数据,此时没有线程安全问题,并发的读取即可;

一个线程读数据一个线程写数据,有线程安全问题;

两个线程都是写数据,也有线程安全问题。

读写锁就是把读和写区别对待,

Java 标准库提供了 ReentrantReadWriteLock 类, 实现
了读写锁.
ReentrantReadWriteLock.ReadLock 类表⽰⼀个读锁. 这个对象提供了 lock / unlock ⽅法
进⾏加锁解锁.
ReentrantReadWriteLock.WriteLock 类表⽰⼀个写锁. 这个对象也提供了 lock / unlock
⽅法进⾏加锁解锁.
其中, 读加锁和读加锁之间, 不互斥. 写加锁和写加锁之间, 互斥. 读加锁和写加锁之间, 互斥.
Synchronized不是读写锁。

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

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

相关文章

基于YOLOv8深度学习的医学影像阿尔兹海默症检测诊断系统研究与实现(PyQt5界面+数据集+训练代码)

阿尔茨海默症(Alzheimer’s disease)是一种常见的神经退行性疾病,主要表现为记忆丧失、认知能力下降以及行为和人格改变。随着全球老龄化问题的加剧,阿尔茨海默症的发病率也在逐年上升,给患者及其家庭带来了巨大的经济…

iOS逆向入门:使用theos注入第三方依赖库

背景 theos是一个跨平台的软件开发框架,常用于管理,开发和部署iOS项目,同时也是开发iOS越狱插件的主要工具。和MonkeyDev不同的是,它不依赖于xcode,可以在多个操作系统上运行。一个完整的iOS越狱开发流程包括&#xf…

STM32电源管理—实现低功耗

注: 本文是学习野火的指南针开发板过程的学习笔记,可能有误,详细请看B站野火官方配套视频教程(这个教程真的讲的很详细,请给官方三连吧) 在响应绿色发展的同时,在很多应用场合中都对电子设备的功…

【FPGA开发】AXI-Stream总线协议解读

文章目录 AXI-Stream概述协议中一些定义字节定义流的定义 数据流类别字节流连续对齐流连续不对齐流稀疏流 协议的信号信号列表 文章为个人理解整理,如有错误,欢迎指正! 参考文献 ARM官方手册 《IHI0051B》 AXI-Stream概述 协议中一些定义 A…

LogViewer NLog, Log4Net, Log4j 文本日志可视化

LogViewer 下载 示例&#xff1a;NLog文本日志可视化软件&#xff0c;并且能够实时监听输出最新的日志 nlog.config 通过udp方式传输给LogViewer (udp://ip:port) <?xml version"1.0" encoding"utf-8" ?> <nlog xmlns"http://www.nlog-…

ES-针对某个字段去重后-获取某个字段值的所有值

针对上面表的数据&#xff0c;现在想根据age分组&#xff0c;并获取每个分组后的name有哪些(去重后)。 select age, GROUP_CONCAT(DISTINCT(name)) from testtable group by age ; 结果&#xff1a; 如果想要增加排序&#xff1a; SELECT age, GROUP_CONCAT(DISTINCT name)…

LabVIEW三针自动校准系统

基于LabVIEW的智能三针自动校准系统采用非接触式激光测径仪对标准三针进行精确测量。系统通过LabVIEW软件平台与硬件设备的协同工作&#xff0c;实现了数据自动采集、处理及报告生成&#xff0c;大幅提高了校准精度与效率&#xff0c;并有效降低了人为操作误差。 一、项目背景…

流程图图解@RequestBody @RequestPart @RequestParam @ModelAttribute

RequestBody 只能用一次&#xff0c;因为只有一个请求体 #mermaid-svg-8WZfkzl0GPvOiNj3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8WZfkzl0GPvOiNj3 .error-icon{fill:#552222;}#mermaid-svg-8WZfkzl0GPvOiNj…

【机器学习】机器学习中用到的高等数学知识-7.信息论 (Information Theory)

熵 (Entropy)&#xff1a;用于评估信息的随机性&#xff0c;常用于决策树和聚类算法。交叉熵 (Cross-Entropy)&#xff1a;用于衡量两个概率分布之间的差异&#xff0c;在分类问题中常用。 信息论作为处理信息量和信息传输的数学理论&#xff0c;在机器学习中具有广泛的应用。…

猎板PCB罗杰斯板材的应用案例

以下是几个猎板 PCB 与罗杰斯板材结合的具体案例&#xff1a; 案例一&#xff1a;5G 通信基站天线 PCB 在 5G 通信基站的天线系统中&#xff0c;对高频信号的传输和处理要求极高。猎板 PCB 采用罗杰斯板材&#xff0c;凭借其稳定的低介电常数&#xff08;如 RO4003C 板材&…

解读InnoDB数据库索引页与数据行的紧密关联

目录 一、快速走进索引页结构 &#xff08;一&#xff09;整体展示说明 &#xff08;二&#xff09;内容说明 File Header&#xff08;文件头部&#xff09; Page Header&#xff08;页面头部&#xff09; Infimum Supremum&#xff08;最小记录和最大记录&#xff09; …

Excel如何把两列数据合并成一列,4种方法

Excel如何把两列数据合并成一列,4种方法 参考链接:https://baijiahao.baidu.com/s?id=1786337572531105925&wfr=spider&for=pc 在Excel中,有时候需要把两列或者多列数据合并到一列中,下面介绍4种常见方法,并且提示一些使用注意事项,总有一种方法符合你的要求:…

uniApp项目运行到鸿蒙手机,应用图标一直是H,应用名一直是HBuilder问题

项目运行到鸿蒙手机&#xff0c;应用图标一直是H,应用名一直是HBuilder问题 应用运行到鸿蒙手机和鸿蒙模拟器&#xff0c;应用图标一直是H,应用名一直是HBuilder&#xff0c;在自动生成的harmony-configs文件夹下也没有配置的文件&#xff0c; 这时候需要你将DevEco Studio 下…

uniapp 自定义加载组件,全屏加载,局部加载 (微信小程序)

效果图 全屏加载 页面加载使用 局部加载 列表加载里面使用 使用gif html <template><view><view class"" v-if"typeFullScreen"><view class"loading" v-if"show"><view class""><i…

鸿蒙实战:使用隐式Want启动Ability

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙应用项目2.2 修改Index.ets代码2.3 创建LuzhouAbility2.4 创建Luzhou页面2.5 设置模块配置文件 3. 测试效果4. 实战总结 1. 实战概述 本次鸿蒙应用实战&#xff0c;先创建项目“ImplicitWantStartAbility”&#xff0c;接着修改In…

NLP论文速读(多伦多大学)|利用人类偏好校准来调整机器翻译的元指标

论文速读|MetaMetrics-MT: Tuning Meta-Metrics for Machine Translation via Human Preference Calibration 论文信息&#xff1a; 简介&#xff1a; 本文的背景是机器翻译&#xff08;MT&#xff09;任务的评估。在机器翻译领域&#xff0c;由于不同场景和语言对的需求差异&a…

AJAX学习(24.11.1-24.11.14)(包含HTTP协议)

AJAX学习&#xff08;24.11.1-11.14) 来源&#xff1a; 传智 | 高校学习平台-首页 传智播课&#xff1a;黑马程序员 1.服务器和客户端 1.服务器&#xff1a;存放和对外提供资源的电脑。 2.客户端&#xff08;用户&#xff09;&#xff1a;获取和消费资源的电脑。&#xff0…

好用的js组件库

lodash https://www.lodashjs.com/https://www.lodashjs.com/ uuid 用于生成随机数&#xff0c;常用于生成id标识 GitHub - uuidjs/uuid: Generate RFC-compliant UUIDs in JavaScripthttps://github.com/uuidjs/uuid dayjs 常用于时间的处理 安装 | Day.js中文网 (fenxi…

基于麒麟服务器操作系统V10版本,部署Nginx服务、MySql服务搭建PHP环境,实现静态网站平台的搭建。

一、环境准备 关闭防火墙。 查看当前防火墙的状态 systemctl status firewalld Copy 如果防火墙的状态参数是inactive,则防火墙为关闭状态。 如果防火墙的状态参数是active,则防火墙为开启状态。 关闭防火墙。 如果您想临时关闭防火墙,需要运行以下命令: systemctl…

[JavaWeb] 尚硅谷JavaWeb课程笔记

1 Tomcat服务器 Tomcat目录结构 bin&#xff1a;该目录下存放的是二进制可执行文件&#xff0c;如果是安装版&#xff0c;那么这个目录下会有两个exe文件&#xff1a;tomcat10.exe、tomcat10w.exe&#xff0c;前者是在控制台下启动Tomcat&#xff0c;后者是弹出GUI窗口启动To…