多线程进阶

这里涉及的内容是关于实现锁 (不只局限于Java的锁),我们作以了解即可。

1.锁策略

1.悲观锁/乐观锁

悲观锁:发生锁竞争的可能性很大------>逻辑更复杂,就是悲观锁

乐观锁:发生锁竞争的可能性很小------>逻辑更简单,就是乐观锁

2.重量级锁/轻量级锁

重量级锁:加锁这个操作开销大------》重量级锁

轻量级锁:加锁这个开销小------》轻量级锁

"加锁":指的是线程代码执行到synchronized上锁时,尝试占有这把锁的整套执行流程,是cpu执行抢锁的全过程。

重量级锁:涉及用户态核心态切换。线程抢不到锁时,交给OS(Operate System)把线程阻塞挂起,放到等待队列,等锁释放后OS唤醒线程。而在这过程中,涉及用户态切换核心态、线程挂起、线程唤醒,CPU要保存、恢复现场等,开销很大

轻量级锁:只涉及用户态。线程抢不到锁时,不会阻塞线程,而是不断重试尝试抢占锁。轻量级锁的优点是没有线程阻塞唤醒的大开销,但明显的缺点是如果线程一直抢不到锁,CPU一置空转,浪费资源。

悲观锁可能是重量级锁,乐观锁有可能是轻量级锁

3.挂起等待锁/自旋锁

挂起等待锁:线程抢不到锁时,交给OS把线程阻塞,让出CPU,等锁被释放时唤醒线程。涉及操作系统内部线程调度,开销大

自旋锁:遇到锁冲突,不会阻塞线程,而是不断重试尝试抢占锁。

但是,注意!!!

自旋锁与轻量级锁不一样。二者的核心策略一样,但不同的是:

自旋锁:无限空转,一直占有CPU,空耗CPU资源

轻量级锁:JVM轻量级锁的自旋时有限制的自适应自旋。即JVM会自动调整自旋次数,预判很快就能拿到锁------自旋,预判长时间抢不到锁,不会空耗CPU资源,会直接升级为重量级锁,交给OS阻塞休眠。

4.公平锁/不公平锁

公平锁:谁先发起抢锁请求,先进入等待队列,等锁释放后就优先唤醒最早排队的线程

非公平锁:释放锁的瞬间,任何线程都可直接竞争抢锁

synchronized是不公平锁,因为如果是公平锁,锁已被占用,多个线程发起抢锁请求,进入阻塞队列,而阻塞队列的线程要被唤醒,这其中涉及操作系统内部线程调度,开销很大。而如果是公平锁,可减少大量线程唤醒的开销,整体并发吞吐量更高。

5.可重入锁/不可重入锁

可重入锁(递归锁):一把锁可多次加锁

不可重入锁:一把锁不可多次加锁

synchronized是可重入锁

6.读写锁/普通互斥锁

普通互斥锁:普通锁是排他锁。即只要一个线程拿到锁,不管是读还是写,其他线程全都排队阻塞。如果1000个线程全是读操作,那么只能串行排队,并发极低。

读写锁:一个线程拿到锁,其它线程可同时拿到锁。具体情况如下:

线程1读+线程2读------》不会发生锁竞争。效率提高

线程1读+线程2写------》发生锁竞争。读锁在读,写锁必须阻塞等读锁释放后才能拿到写锁;

写锁在修改,其它读锁阻塞,等写锁释放后再拿到读锁。

线程1写+线程2写:------》发生锁竞争。

synchronized是普通互斥锁。

相关推荐
「QT(C++)开发工程师」23 分钟前
C++ 11 常用for循环
开发语言·c++
我还记得那天33 分钟前
0 初识C++
开发语言·c++
FfHUCisI1 小时前
Go 编译过程全景
开发语言·后端·golang
FfHUCisI1 小时前
Golang 语法分析与 AST:Parser 与 go/ast
开发语言·后端·golang
保定公民1 小时前
达梦数据库存储过程中的数组类型详解:基础数组与记录数组的差异化应用
数据库·达梦·存储过程·达梦数据库·dm8·dm
秋饼1 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
梦Arrebol2 小时前
Redis 内容及相关实验
数据库·redis
卓怡学长2 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk2 小时前
ObjectProperty
java·开发语言·算法