锁优化
自旋锁与自适应自旋:
自旋:如果线程可以很快获得锁,那么可以不在OS层挂起线程,而是让线程做几个忙循环,那么就是自旋
自适应自旋:自旋的时间不再固定,而是由前一次在同一个锁上的自旋时间和锁的拥有者状态来决定
适用在:如果锁被占用时间很短,自旋成功,那么能节省线程挂起、以及切换时间,从而提升系统性能
如果锁被占用时间很长,自旋失败,会白白耗费处理器资源,降低系统性能
锁消除:
在编译代码的时候,检测到根本不存在共享数据竞争,自然也就无需同步加锁了;通过: -XX:+EliminateLocks来开启
❤同时要使用-XX:+DoEscapeAnalysis开启逃逸分析,所谓逃逸分析:(1)如果一个方法中定义的一个对象,可能被外部方法引用,称为方法逃逸
(2)如果对象可能被其他外部线程访问,称为线程逃逸,比如赋值给类变量或者可以在其他线程中访问的实例变量
锁粗化:
❤通常我们都要求同步块要小,但一系列连续的操作会导致对一个对象反复的加锁和解锁,这会导致不必要的性能损耗。这种情况建议把锁同步的范围加大到整个操作序列。
轻量级锁:
轻量级相对于传统锁机制而言,本意是没有多线程竞争的情况下,减少传统锁机制使用OS实现互斥所产生的性能损耗。
其实现原理很简单,就是类似乐观锁的方式
如果轻量级锁失败,表示存在竞争,升级为重量级锁,导致性能下降
偏向锁:
偏向锁是在无竞争情况下,直接把整个同步消除了,连乐观锁都不用,从而提高性能,所谓的偏向,就是偏心,即锁会偏向于当前已经占有锁的线程
只要没有竞争,获得偏向锁的线程,在将来进入同步块,也不需要做同步
当有其他线程请求相同的锁时,偏向模式结束
如果程序中大多数锁总是被多个线程访问的时候,也就是竞争比较激烈,偏向锁反而会降低性能
使用-XX:-UseBiasedLocking来禁用偏向锁,默认开启
JVM中获取锁的步骤:
会先尝试偏向锁;然后尝试轻量级锁
再然后尝试自旋锁
最后尝试普通锁,使用OS互斥量在操作系统层挂起
同步代码的基本规则:
尽量减少锁持有的时间
尽量减小锁的粒度(锁里面包含的功能不要太多,要精简)