自旋锁与自适应自旋
虚拟机团队注意到许多应用上,共享数据的锁定状态只会持续很短的一段时间,
为了这段时间去挂起和恢复线程并不值得。
可以让后面请求锁的那个线程“稍等一会”,但不放弃处理器的执行时间,看持有锁
的线程是否很快就会释放锁。为了让线程等待,只需让线程执行一个忙循环(自旋),
这项技术就是所谓的自旋锁。
自旋锁
自旋锁在JDK1.4.2
引入,默认是关闭的,可用-XX:UseSpinning
参数来开启,在
JDK6
改为默认开启。
自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的,所以如果
锁被占用的时间很短,自旋等待的效果就会很好,否则自旋的线程只会白白消耗
处理器资源。因此自旋等待的时间必须有一定的限度,如果自旋超过限定的次数
仍没获得锁,就应当使用传统的方式去挂起线程。自旋次数的默认值是10次,可以
使用-XX:PreBlockSpin
进行设置。
自适应自旋
JDK6
对自旋锁进行优化,自适应自旋意味着自旋的时间不再是固定的,而是由前一次
在同一个锁上的自旋时间及锁拥有者的状态来决定的。
如果在同一个锁对象上,自旋等待刚刚获得过锁,并且持有锁的线程正在运行中,那么
虚拟机就会认为这次自旋也很有可能再次成功,进而允许自旋等待持续相对更长时间。
如果对于某个锁,自旋很少成功获得过锁,那以后获取这个锁将可能直接省略掉自旋过程。
有了自适应自旋,随着程序运行时间的增长及性能监控信息的不断完善,虚拟机对程序锁
的状态预测就会越来越精准。