【JavaEE“多线程进阶”】——各种“锁”大总结

devtools/2024/9/29 10:04:55/

8e19eee2be5648b78d93fbff2488137b.png

阿华代码,不是逆风,就是我疯,

你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!

目录

一:乐观锁和悲观锁

1:乐观锁

2:悲观锁

3:总结

二:轻量级锁和重量级锁

1:轻量级锁

2:重量级锁

3:总结

三:自旋锁和挂起等待锁

1:自旋锁

2:挂起等待锁

四:普通互斥锁和读写锁

1:普通互斥锁

2:读写锁

(0)知识联系

(1)此处解释

(2)总结

3:为什么引入读写锁

(1)场景一

(2)场景二

(3)优化

五:公平锁和非公平锁

1:两者对比

六:可重入锁和不可重入锁

七:synchronized自适应阶段

1:偏向锁阶段

2:轻量级锁阶段

3:重量级锁阶段

4:总结

八:锁消除

九:锁粗化

1:“粒度”

2:定义


一:乐观锁和悲观锁

1:乐观锁

在加锁过程中,预估发生锁冲突的概率小,降低加锁的工作量,加锁的效率就提高了,安全系数不高(可能会引发占用大量cpu资源的问题)

2:悲观锁

在加锁过程中,预估发生锁冲突的概率大,提升加锁的工作量,加锁的效率就下降了,但是安全系数高

3:总结

乐观锁——牺牲安全性换来效率

悲观锁——牺牲效率换来安全性

二:轻量级锁和重量级锁

引入:在乐悲观的基础上延伸出来的

1:轻量级锁

加锁的开销小,速度快——一般指乐观锁

2:重量级锁

加锁的开销大,速度慢——一般指悲观锁

3:总结

乐/悲观锁是加锁前对没有发生的事情的预估

轻/重量锁是加锁后对结果的评价

整体上来说,两者都是在对一件事情进行描述

三:自旋锁和挂起等待锁

1:自旋锁

自旋锁是轻量级锁的一种实现,也是乐观锁,通过与一个while循环搭配,如果获取到锁,那就结束循环;如果没有获取到锁,不会阻塞放弃cpu,而是继续下一次循环,直到获取到锁

(1)使用场景:锁冲突不激烈

(2)优点:其它线程一旦释放锁,就能快速获取到锁

(3)缺点:会占用消耗大量的cpu资源

2:挂起等待锁

挂起等待锁是重量级锁的一种实现,也是悲观锁,锁释放后并不能第一时间获取到锁,而是要通过操作系统的内核进行调度去获取锁,这个等待的过程时间较长。

(1)使用场景:锁冲突激烈

(2)优点:在内核调度的等待时间中,cpu可以做别的事情,即降低了cpu的资源消耗

(3)缺点:不能第一时间获取到锁

四:普通互斥锁和读写锁

1:普通互斥锁

与synchronized相似,可以进行加锁和解锁

2:读写锁

(0)知识联系

想想之前文章写到的MySQL事务处理——三读

“脏读”——给写加锁(写的时候不能读)

“不可重复读”——给读加锁(读的时候不能写)

“幻读”——读写都加上锁

(1)此处解释

读锁和读锁之间,不会发生锁冲突(不会阻塞)

写锁和写锁之间,会发生锁冲突(会阻塞)

读锁和写锁之间,会发生锁冲突(会阻塞)

(2)总结

一个线程加读锁的时候,另一个线程只能读,不能写

一个线程加写锁的时候,另一个线程只能写,不能读

3:为什么引入读写锁

(1)场景一

两个线程一起读,本身就是线程安全的不互斥,如果使用synchronized,就让两者互斥了

(2)场景二

如果一个线程读,一个线程写,也是不可以的(参考MySQL事务那一章节)

(3)优化

在实际开发中,本身读操作就是非常频繁的,引入读写锁可以大大节省下来“并发读”带来的锁冲突的资源消耗,

五:公平锁和非公平锁

1:两者对比

我们知道线程遵守“随机调度”的原则,所以在在加锁过程中就产生了“锁竞争”这一现象,在“Java”中规定公平就是遵守“先来后到”这一原则,synchronized本身就是非公平锁——一旦解锁,下一个加锁的线程是无法确定的。

所以我们引入队列,记录每个线程的顺序,依次加锁,实现“公平锁”

六:可重入锁和不可重入锁

一个线程对同一个对象加了两次锁,不会产生死锁,根据{}和内置的计数器来确定真正加锁和解锁的位置,synchronized就是可重入锁(推荐看看阿华之前写的那篇《多重入锁》文章哈)

系统自带的锁一般是不可重入锁。

七:synchronized自适应阶段

IDEA中提供的synchronized加锁具有自适应能力,内部会自动评估当前锁冲突的激烈程度,在乐观锁(系列:乐观锁,轻量级锁,自旋锁)和悲观锁(系列:悲观锁,重量级锁,挂起等待锁)中进行筛选。

这也是一种优化方式

1:偏向锁阶段

假设现在有一把偏向锁,A线程拿上了这把锁,不是真正意义上的加锁(假加锁),而是让这把锁对A线程有一个(轻量)标记,如果有其他的线程竞争也想要拿上这把锁,那A就会先一步加锁(真加锁)。

理解:

偏向锁标记是对象里头的一个属性,每个锁对象都有这么一个标记,锁对象首次被加锁都会先进入偏向锁阶段

如果没有锁竞争,那么下次加锁,还是会进入偏向锁阶段。

如果在加锁的过程中遭遇“锁竞争”,那么就会升级为“轻量级锁”阶段,

优点:非必要不加锁,没有锁竞争,偏向锁能大大提高效率

彩蛋:锁先生舔着女神A,女神A吊着锁先生就是不跟他确认关系,忽然有个姑娘B加入进来,想和锁先生确认关系,女神A就慌了~,赶快跟锁先生就确认男女朋友了,像极了爱情~~~

2:轻量级锁阶段

通过“自旋锁”的方式实现,synchronized内部也会统计有多少个线程在“锁竞争”,因为一旦超过某一个线程数量限制,大量的自旋锁会非常消耗cpu资源,此时就会升级为“重量级锁阶段”

优点:其他线程一旦释放锁,就能快速拿到锁

缺点:非常消耗cpu资源

3:重量级锁阶段

承接上文,此时线程放弃自旋锁,进入“阻塞等待”,当解锁后,系统在随机唤醒线程进行加锁。

4:总结

以上synchronized加锁的三个阶段是层层递进升级的,在目前Java中是不能够降级的,

八:锁消除

假如一个线程加了锁,但是一眼看过去这个线程肯定没有线程安全问题,那么在编译器编译代码的时候就会自动“消除锁”,提高效率。

针对一些模棱两可的代码,编译器不知道要不要加锁,统一都不会进行锁消除

九:锁粗化

1:“粒度”

synchronized{}花括号中的代码数量越少,则称锁的粒度越细;代码越多,锁的粒度越粗

2:定义

把多个细粒度的锁,合并成一个粗粒度的锁,就叫锁粗化

锁粗化也是为了提高效率,它跟可重入锁可不一样哦


http://www.ppmy.cn/devtools/118638.html

相关文章

安全类面试题-填空题

填空题 1、Linux下,复制/root/soure 到当前目录的命令是 cp -r /root/soure ./ 2、Linux下,解压缩bz2格式文件的命令是 bzip2 -d FileName 3、Linux下,查看网络连接状态的命令是 netstat 4、数据库触发器能监控的触发事件有: upda…

macOS与Ubuntu虚拟机使用SSH文件互传

1.ubuntu配置: 安装openssh服务: sudo apt-get install openssh-server -y 查看服务启动状态: systemctl status ssh 2.macOS使用scp连接ubuntu并发送文件 查看ubuntu IP : ifconfigmacOS终端连接ubuntu : sc

在系统开发中提升 Excel 数据导出一致性与可维护性的统一规范与最佳实践

背景: 在系统开发过程中,数据导出为 Excel 格式是一个常见的需求。然而,由于各个开发人员的编码习惯和实现方式不同,导致导出代码风格不一。有的人使用第三方库,有的人则自定义实现。这种多样化不仅影响了代码的一致性…

2024热门AIPPT工具大盘点

随着人工智能技术的飞速发展,一种全新的 PPT 制作方式应运而生——Ai 制作 PPT。它如同一位智能助手,为我们带来了高效、创新且个性化的 PPT 制作体验。今天我们一起探讨有哪些工具可以助力我们轻松打造出令人惊艳的演示文稿的。 1.笔灵AIPPT 链接一下…

LINUX--调度未来任务

crontab 文件中的用户作业时间格式怎么解释? * * * * * command 分 时 日 月 周 x-y表示范围,包括x,y的值 */x 表示x的间隔 x,y表示列表&am…

【60天备战2024年11月软考高级系统架构设计师——第30天:云计算与大数据架构——云计算架构设计原则】

在现代软件开发中,云计算架构的设计原则为系统提供了灵活性、可扩展性和高可用性。理解这些原则能够帮助架构师在构建云应用时作出明智的决策。 云架构设计原则 可伸缩性:系统应该能够根据需求的变化动态调整资源。这包括垂直伸缩(增强单个…

Qt_网络编程

目录 1、Qt的UDP Socket 1.1 用Udp实现服务器 1.2 用Udp实现客户端 2、Qt的TCP Socket 2.1 用Tcp实现服务器 2.2 用Tcp实现客户端 3、Qt的HTTP 3.1使用Qt的HTTP 结语 前言: 网络协议是每个平台都必须遵守的,只是不同的平台所提供的网络API不…

pdf.js滚动翻页的例子

可以使用 pdf.js 创建一个简单的滚动翻页效果。以下是一个基本示例&#xff0c;展示如何实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthd…