Java中常见的锁策略

本文详细介绍了Java中的锁策略,包括悲观锁与乐观锁、重量级锁与轻量级锁的区别,以及挂起等待锁与自旋锁、读写锁与普通互斥锁、公平锁与非公平锁、可重入锁与不可重入锁的概念。同时,文章讨论了synchronized的锁优化机制,如锁膨胀、锁粗化和锁消除,并对比了ReentrantLock与synchronized的异同。此外,还提及了Semaphore信号量和CopyOnWriteArrayList的使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.悲观锁和乐观锁:处理所冲突的态度(原因)

悲观锁:预期锁冲突的概率很高,做的工作更多,付出成本更多,更低效
乐观锁:与其所冲突的概率很低,做的工作更少,付出成本很低,更高效

2.重量级锁和轻量级锁:处理所冲突的结果

重量级锁:做了更多的事情,开销更大
轻量级锁:做的事更少,开销更小 也可以认为通常情况下,悲观锁一般都是重量级锁,乐观锁一般都是轻量级锁
在使用的锁中,如果锁是基于内核的一些功能来实现(比如调用了操作系统的mutex接口)此时一般认为是重量级锁。如果锁是纯用户态实现,此时一般认为这是轻量级锁。

3.挂起等待锁和自旋锁:

挂起等待锁:往往通过等待内核的一些机制来实现,一般较重(重量级锁的一种典型实现)
自旋锁:往往通过用户态代码来实现,一般较轻(轻量级锁的一种典型实现)

4.读写锁和普通互斥锁:

普通互斥锁:只有加锁和解锁两个操作
读写锁:分成三个操作
加读锁ReentrantReadWriteLock.ReadLock:如果代码指示进行读操作就加多操作
加写锁ReentrantReadWriteLock.WriteLock:如果代码中进行了修改操作就加写锁
解锁

5.公平锁和非公平锁

公平锁:多个线程在等待同一把锁的时候,谁先来的就能获取到这个锁(遵守先来后到)
非公平锁:多个线程在等待一把锁的时候,不遵守先来后到(每个等待的线程获取到锁的概率都是均等的),对于操作系统来说,线程之间的调度就是随机的,所以操作系统的mutex这个锁就是非公平锁。

6.可重入锁和不可重入锁

一个线程针对一把锁重复加锁,产生死锁就是不可重入锁,不会死锁就是可重入锁

synchronized总结

1.既是一个乐观锁也是一个悲观锁(根据锁竞争激烈程度自适应)
2.不是读写锁,是一个普通互斥锁
3.既是一个轻量级锁,也是一个重量级锁(根据锁竞争激烈程度自适应)
4.轻量级锁的部分基于自旋锁来实现,重量级锁部分基于挂起等待锁来实现
5.非公平锁
6.可重入锁

synchronized中的锁优化机制
1.锁膨胀/锁升级

体现了synchronized能够自适应的能力

无锁->
偏向锁(首个线程加锁,就会先进入偏向锁的状态,偏向锁不是真的锁只是做了个标记而已)->
自旋锁(又有其他线程加锁产生竞争了,进入了轻量级锁)->
重量级锁(如果竞争进一步加剧,就会进入重量级锁状态)

2.锁粗化

这里的粗细指的是“锁的粒度”,即是加锁代码所涉及的范围,范围越大锁的粒度越粗,范围越小锁的粒度越细。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值