多线程--常见锁策略--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,一经查实,立即删除!

相关文章

Vue和Vue-Element-Admin(十四):vue3.x与vue2区别分析

目录 vue3.x组合式api vue2 定义属性和方法 vue3 定义属性和方法 router 使用的区别 vue2.x router使用 定义router 在main.js中引入router 在vue中使用 vue3.x使用router 定义router 在main.js中引用 在vue中使用router 定义全局方法,变量 vue2.x定义全局方法 …

将大模型生成数据存入Excel,并用增量的方式存入Excel

将大模型生成数据存入Excel,并用增量的方式存入Excel 1. 需求与要解决的问题2. 代码3. 部分代码分析 1. 需求与要解决的问题 首先就是大模型对话特别耗时,所以通过需要异步执行。 其次是中间对话会有终端或像死锁的那种情况,循环不再继续&am…

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

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

鸿蒙学习生态应用开发能力全景图-鸿蒙开发套件(2)

文章目录 1、HarmonyOS 设计套件2、开发套件3、测试套件3.1测试标准3.2测试工具4、运维套件4.1上架分发测试能力4.2运维分析1、HarmonyOS 设计套件 Harmony Design 是面向全场景智能体验的设计系统,致力于构建一个和谐的数字世界,其秉承万物归一、和谐共生、衍生万物的设计理…

记一次 MongoDB 选主问题的解决及分析

目录 一、副本集构成 二、问题发生与解决 三、问题分析 1. 为何触发重新选举 2. 主何时被认为已失效 3. 选主过程 4. 关于候选节点(Candidate Node) (1)候选节点的定义 (2)候选节点的产生条件 &a…

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

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

mysql8.4+mysql router读写分离

以下为容器环境内搭建 准备工作: 拉取镜像: 镜像版本mysql8.4container-registry.oracle.com/mysql/community-router8.4 下载mysql_shell mysql-shell-9.0.1-linux-glibc2.17-x86-64bit.tar.gz 下载地址: https://downloads.mysql.com/archives/shell/ 参考 这里对这篇文章…

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; …

【UNIAPP】uniapp版图片压缩工具

二次封装的uniapp版本图片压缩、上传工具&#xff0c;支持全端&#xff08;H5、小程序、APP&#xff09; 新建文件&#xff1a;file-util.js class FileUtil {/*** [文件上传]* param {[object]} fileObj [图片地址]* param {[object]} formData [参数]* param {[str…

Python去除图像白色背景

使用Pillow去除图像背景 安装依赖&#xff1a; pip install pillow 实现步骤&#xff1a; 使用Pillow库加载图像&#xff0c;并将其转换为RGBA模式&#xff0c;以支持透明度。遍历图像的每个像素&#xff0c;检查其红色、绿色和蓝色值是否都高于预设的阈值。对于被视为白色…

Spring Cache之本地缓存注解@Cacheable,@CachePut,@CacheEvict使用

*使用前需要在启动类上添加一个注解&#xff1a;EnableCaching 先说一下SpringCache是不支持灵活的缓存时间设置的&#xff0c;但可以自己实现。且不支持集群&#xff0c;因为是缓存到每台机器上&#xff0c;除非所有机器都有缓存。 所以使用场景一般是数据量较小的单机服务。…

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

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