这是我新开的一个文章系列,意在以500字左右的短文章的形式初步讲解复杂的知识点,便于随时查看和学习。
这个系列每天都会更新,一定要关注呀。
在JDK1.6之前,只要使用了synchornized
关键字,加的就是重量级锁。但是由于重量级锁涉及用户态和内核态的切换,性能不佳,在JDK1.6之后为了优化性能,出现了偏向锁和轻量级锁(自旋锁)。有了这两种锁之后,使用synchronized关键字并不会一上来就加重量级锁,而是存在一个锁升级的过程,如下图所示。并且这个过程是不可逆的,只能升级不能降级。
简单来说,如果开启了偏向锁(JDK1.6之后默认开启且默认JVM启动后4秒开启),对象在new出来之后就会进入一种“匿名偏向”状态——并没有真的加偏向锁,但是对象头部的markword标记与偏向锁一样为101,当有线程访问这个对象时,会把自己的id写入markword中给这个对象加上偏向锁。如果没有开启偏向锁,synchronized标记的对象就会直接加轻量级锁。
如果在线程竞争偏向锁时有线程等待时间过长,或者线程调用了wait()方法,就会直接给对象加重量级锁。
每一种锁在对象markword里的标记都不一样,如下图所示。注意这里的其他部分没有详细写出,实际上markword中存储的信息很复杂,以后再做总结。如果看到11,就是这个对象被GC标记了。
补充:
- 如果一个对象的identity hashCode被计算过,它就无法被加偏向锁(这里的identity hashCode是没有被重写的java.lang.Object中的hashCode);
- 如果一个对象持有偏向锁,这时要计算identity hashCode的话,它所加的偏向锁会被撤销,并且直接膨胀为重量级锁。