在JVM启动以后,默认有4s的偏向延迟时间,意思就是,在JVM启动的时候,4s中以内创建的对象是默认为不可偏向的。例如static 静态对象。可以用代码来验证一下
朴实无华类A,用于加锁
package com.edu.enior.bf.objheaderedu;public class A {}
验证类
package com.edu.enior.bf.objheaderedu;import org.openjdk.jol.info.ClassLayout;public class PrintObjInfo {//静态对象static A a = new A();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {lockTest();});t1.setName("t1");t1.start();}static void lockTest(){synchronized (a){//打印线程名称System.out.println(Thread.currentThread().getName());//查看对象内存信息System.out.println(ClassLayout.parseInstance(a).toPrintable());}}}

可以看到00,00代表的是轻量锁
接下来让主线程休眠6秒
package com.edu.enior.bf.objheaderedu;import org.openjdk.jol.info.ClassLayout;public class PrintObjInfo {public static void main(String[] args) throws InterruptedException {Thread.sleep(6000);//在休眠之后创建锁对象A a = new A();Thread t1 = new Thread(() -> {lockTest(a);});t1.setName("t1");t1.start();}static void lockTest(A a){synchronized (a){//打印线程名称System.out.println(Thread.currentThread().getName());//查看对象内存信息System.out.println(ClassLayout.parseInstance(a).toPrintable());}}}

此时10为偏向锁。
偏向延迟的原因
因为JVM启动的时候,需要用到很多锁,但是对于偏向锁,有一个偏向撤销操作,偏向撤销是一个非常耗资源的操作,所以JVM的开发者,就直接先把偏向锁设置为JVM启动4s以后。可以通过以下命令来维护JVM偏向锁状态
//关闭偏向延迟-XX:BiasedLockingStartupDelay=0//禁用偏向锁-XX:-UseBiasedLocking//启用偏向锁-XX:+UseBiasedLocking
偏向撤销
应用
有些时候,在线上环境,能确定自己加了synchronized关键字的方法是被一个线程调用的才开启偏向锁,一般线上的项目,基本上都是把偏向锁关闭的,原因就是偏向撤销太耗资源。
