1、悲观锁与乐观锁
(1)悲观锁与乐观锁
悲观锁
乐观锁
(2)执行流程
悲观锁
多个线程尝试获取同步资源的锁(给同步资源加锁)
某个线程加锁成功并执行操作,其他线程进入等待
获取到锁的线程执行完成之后会释放锁,然后CPU唤醒等待的线程,被唤醒的线程再次尝试获取锁
乐观锁
线程直接获取同步资源数据执行各自的操作
更新内存中的同步资源之前先判断资源是否被其他线程修改。没有被修改,就可以更新内存中同步资源的值;被其他线程修改的话就根据实现方法执行不同的操作
2、CAS算法(Compare And Swap)
(1)概念
(2)流程
(3)CAS存在的问题
ABA问题:
循环时间开销比较大
只能保证一个共享变量的原子操作
3、自旋锁
(1)概念
是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,白旋直到获取到锁才会退出循理
(2)自旋锁存在的意义与使用场景
阻塞与唤醒线程需要操作系统切换CPU状态,需要消耗一 定时间
同步代码块逻辑简单,执行时间很短
自适应自旋假定不同线程持有同一个锁对象的时间基本相当,竞争程度趋于稳定,因此,可以根据上一次自旋的时间与结果调整下一次自旋的时间。例如:上次35次成功了,但是这一次35次了还没有成功,那么就会考虑多加一点次数。如果还没有成功,超出自旋的上限就会认为自旋成功的几率越来越低,后续的话会对其进行降级,减少自旋上限
JDK1.6通过-XX:-UseSpinning参数关闭自旋锁优化;-XX:PreBlockSpin参 数修改默认的自旋次数。 JDK>=1.7自旋锁的参数被取消,虚拟机不再支持由用户配置自旋锁,自旋锁总是会执行,自旋锁次数也由虚拟机自动调整。
(3)源码
4、synchronized分析(https://fanyi.baidu.com/?aldtype=16047#en/zh/synchronized)
(1)使用方式
同步实例方法,锁是当前实例对象
同步类方法,锁是当前类对象
同步代码块,锁是括号里面的对象
(2)实现方式
synchronized是JVM内置锁,通过内部对象Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器锁的实现依赖底层操作系统的Mutex lock (互斥锁)实现
(3)每一个同步对象都有自己的Monitor(监视器锁)
线程进入同步块,首先要判断当前线程对象是否拿到了监视器锁,拿到的话才能进入到同步块,没有拿到的话会进入同步队列排队,当其他线程释放锁以后再唤醒,进行下一轮尝试获取锁的操作
(4)JVM内置锁的膨胀升级
这个过程不能逆向,可以释放锁,然后从偏向锁状态开始升级
锁:主流锁整体认知(悲观锁与乐观锁、CAS算法、自旋锁、synchronized分析)
原文:https://www.cnblogs.com/zhai1997/p/13467606.html