Synchronized & Lock
- Synchronized 能够用于类,办法,代码块加锁;Lock 只能作用于代码块
- Synchronized 不须要手动获取锁,开释锁,更简略;Lock 如果没有 unlock()可能会带来一些问题
- Lock 能够通过 lock()判断是否获取到了锁,而 Synchronized 不能
Synchronized & ReentrantLock
- 二者皆为可重入锁
- Synchronized 基于 JVM 实现(monitorenter 指令);ReentrantLock 基于 API 实现(能够了解为,一个在机器码层,一个在应用层)
- ReentrantLock 性能更加全面,反对偏心非偏心模式,反对中断并放弃获取锁,反对 Condition 来实现线程之间的调度,更加灵便
应用抉择
- 除非须要应用到 ReentrantLock 的高级性能,尽量应用 Synchronized,更简略,JVM 原生反对
Synchronized 锁的降级
降级程序为 无锁》偏差锁》轻量锁》分量锁
Synchronized 应用的锁寄存在 Java 对象头的 MarkWord 里,其中存储了同步状态、标识、hashcode、GC 状态等信息
- 偏差锁
少数状况下,锁的应用并不存在多线程竞争,并且总是由同一个线程取得;因而引入偏差锁,升高线程首次取得锁的代价;偏差锁会偏差于第一个拜访锁的线程,在程序运行中,只有一个线程拜访同步锁,不存在多线程争用的状况,则线程不须要触发同步,间接给该线程加一个偏差锁 - 轻量锁
当产生锁的竞争时,偏差锁会降级为轻量级锁,轻量锁是自旋锁;轻量锁的设计思维是,如果持有锁的线程可能在很短时间内开释锁,则期待的线程能够不作上下文切换,只是进行数次自旋期待,持有锁的线程开释锁后即可立刻获取锁,从而防止上下文切换的开销(上下文切换比执行 CPU 指令的开销要大的多) - 分量锁
线程自旋是须要占用 CPU 的,因而须要设定一个自旋期待的最大工夫,当持有锁的线程执行的工夫超过自旋期待的最大工夫扔没有开释锁,则竞争锁的线程会进行自旋进入阻塞状态,此时降级到重量级锁,JDK1.6 中引入了适应性自旋锁,自旋的工夫不再固定,而是由上一次在同一个锁上的自旋工夫以及锁的拥有者的状态来决定,根本认为是一个线程上下文切换的工夫
参考资料:
https://blog.csdn.net/m0_6965…