偏向锁
轻量级锁在没有竞争时(只有自己一个线程),仍然会尝试CAS替换mark word;
会造成一定的性能的损耗;
JDK6之中引入了偏向锁进行优化,第一次使用时线程ID注入到Mark word中,之后重入不再进行CAS自旋替换操作;
markword格式
我们回忆一下mark word格式
其中biased_lock值:
- 为0表述没有开启偏向锁;
- 为1表示开启了偏向锁;
我们可以看到开起偏向锁,存放的不再是hash了,而是线程thread;
一个对象创建时
-
使用了偏向锁,markword最后三位为101,一般默认开启偏向锁(偏向锁有延迟,会在对象创建后一会才有偏向锁);
测试
加锁时测试
加锁后会多出现线程id部分;除非其他线程使用,线程id不会改变;
禁用偏向锁
添加VM参数
结果
加锁时00表示轻量级锁
锁释放后线程标识会被清除;
在优先级上先偏向锁,让后轻量级锁,最后产生竞争膨胀为重量级锁;
测试hashcode
因为hash占31位,首次调用时hashcode填充31位,这时没有足够的位数存储thread,所以调用hashcode方法,锁为轻量级而非偏向锁;
偏向锁撤销
当有其他线程使用偏向锁时,会将偏向锁升级为轻量级锁;
测试
无论是轻量级锁还是偏向锁都是错开执行的,我们利用wait和notify让其错开执行;