在项目中发现偏向锁并不是立即生效的,而是有着一个默认延迟,下面深入探究一下,为什么偏向锁有着四秒延迟,以及怎么调优
问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public class JOL { public static void main(String[] args) { Object o = new Object(); System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){ System.out.println(ClassLayout.parseInstance(o).toPrintable()); } } }
|
打印:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 28 f2 5a 03 (00101000 11110010 01011010 00000011) (56291880) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
|
然后我们发现,我们明明添加了synchronized,为什么第二次的打印信息为00
不应该是01吗,开始jvm是使用的偏向锁,偏向锁是101啊
探究
原因:
创建一个对象后,jvm偏向锁的启动是有4秒延时的(默认),这个时候为匿名偏向,因为在开始创建的过程中肯定有大量的线程参与竞争(内存分配的竞争等等),这个时候如果立即打开偏向锁的话,肯定是有性能浪费的(锁竞争过程、锁撤掉),所以打开偏向锁的效率不是一定会提升效率。
这个时候我们,在代码最前面添加睡眠5秒钟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public class JOL { public static void main(String[] args) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } Object o = new Object(); System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){ System.out.println(ClassLayout.parseInstance(o).toPrintable()); } } }
|
打印:
这个时候状态为101,才升级为偏向锁
调整默认参数
1 2
| #jvm中设置立即打开偏向锁 -XX:BiasedLockingStartupDelay=0
|
然后注释掉睡眠5秒钟
打印: