JVM调优之——禁用偏向锁优化

JVM调优之——禁用偏向锁优化

JVM参数

-XX:-UseBiasedLocking //关闭偏向锁(默认打开)

或者

-XX:+UseHeavyMonitors //设置重量级锁

使用条件

STW的开销>用户态与内核态切换的开销

如果你想了解原理,请往下看

首先我们来复习几个概念

用户态与内核态

操作系统中的程序,一般都是在用户态下运行的。当程序需要借助操作系统来完成一些自己无法完成的操作时,便会从用户态切换到内核态,如果频繁切换,这样的开销还是很大的

重量级锁

其实现原理是通过操作系统调用MutexLock来保证竞态资源的互斥,所以会产生用户态与内核态的切换

CAS

比较实际内存值与预期内存值,相同则更新内存值,否则什么都不做(这是Java调用的一串cpu指令,不具体讨论)

更新失败的原因就是各个线程cpu缓存的可见性问题

偏向锁

偏向锁只有在出现竞争的时候才会释放。在一个线程尝试获取偏向锁时,JVM会对比该线程ID与锁对象头中的线程ID,相同则说明该线程已经持有该锁,直接执行同步方法;不同则通过CAS操作改变对象头中的线程ID。可见与重量级锁相比,偏向锁降低了用户态与内核态切换的开销

虽然偏向锁起到了优化作用,但是也有弊端

在并发程度相对较大的程序中,CAS改变对象头线程ID有可能失败,这时会导致撤销偏向锁,并尝试将偏向锁升级为轻量级锁。偏向锁的撤销操作会在全局安全点(safepoint)暂停当前持有该锁的线程,如果此时该线程没有执行同步方法,则该线程释放锁,同时其他线程重新竞争对象锁,否则将锁升级。在这里频繁地撤销偏向锁会导致线程长时间暂停,也是很大的开销

撤销偏向锁会让持锁线程暂停,是因为当CAS改变对象头线程ID失败后,需要根据持锁线程状态判断,是将锁变为无锁状态还是升级为轻量级锁。如果不暂停持锁线程,可能判断线程状态的时候还是运行状态,决定将锁对象升级为偏向锁;但升级之前线程又结束了,需要释放锁,这样会产生冲突锁头状态的冲突

所以当线程暂停的时间大于偏向锁带来的用户态与内核态切换节省下来的时间时,我们需要禁用偏向锁优化

你可能感兴趣的:(jvm)