什么是 Java 中的锁自适应自旋?
什么是 Java 中的锁自适应自旋?
回答重点
锁自适应自旋 是 Java 锁优化中的一种机制,用于减少线程在竞争锁时频繁挂起和恢复的开销。
自适应自旋的核心思想是,在锁争用较少的情况下,线程在进入等待状态前,先执行一段自旋操作(即短暂忙等),而不是立刻挂起线程。
在 Java 中 Syncronized 在争抢重量级锁时候会自旋。具体指的是在重量级锁时,一个线程如果竞争锁失败会进行自旋操作,说白了就是执行一些无意义的执行,空转 CPU 等着锁的释放。
原理:
- 自旋:当一个线程尝试获取锁失败时,它会先忙等一段时间,即自旋,而不是立刻进入阻塞状态。自旋指的是线程反复检查锁是否释放的操作。
- 自适应性:自适应自旋锁通过动态调整自旋的次数来提高性能。自适应的策略基于之前的自旋结果,假如上一次自旋很快获得了锁,下次可能会增加自旋次数;如果自旋失败,则减少自旋时间甚至直接放弃自旋。
优点:
- 自旋可以避免线程的上下文切换开销,因为线程进入阻塞状态会涉及到操作系统层面的挂起和唤醒,代价较高。
- 自适应自旋通过动态调整自旋次数,使得在轻度锁争用情况下的性能提升显著。
缺点:
- 如果锁争用激烈,自旋可能会白白浪费 CPU 时间,因此自适应自旋需要合理的机制来判断是否应该继续自旋。
扩展知识
自适应自旋扩展
在 Java 中,锁通常是由操作系统的同步原语(如 mutex)实现的。当线程无法获取锁时,通常会被操作系统挂起,这会涉及到线程状态的转换和 CPU 上下文的切换,代价较高。而自旋锁避免了这种高开销操作。
在 HotSpot JVM 中,自适应自旋是默认开启的,且锁的自旋次数根据上一次锁的争用情况动态调整,具体实现可以参考 LockingMechanisms.cpp 文件中的 AdaptiveSpinLock 部分。
自适应自旋的调优:
- 在 JVM 中,可以通过
-XX:+UseSpinning参数启用或关闭自旋锁,并通过-XX:PreBlockSpin参数调整自旋的次数。 - 但是,JVM 默认的自适应自旋已经做了合理优化,手动调整这些参数的场景不多。
自适应自旋通俗理解
形象一点就像怠速停车和熄火的区别,如果等待时候很长(长时候都拿不到锁),那肯定熄火划算(阻塞)。
如果一会儿就要出发(拿到锁),那怠速停车(自旋)比较划算。
不过因为这个自旋次数不好判断,所以引入自适应自旋。
说白了就是结合经验值来看,如果上次自旋一会儿就拿到锁,那这次多自旋几次,如果上次自旋很久都拿不到,这次就少自旋。
这就叫锁的自适应自旋。
Comments