面试:什么情况下,轻量级锁会升级为重量级锁?

上代码:

  1. public class MarkWordTest {
  2. @Test
  3. public void test8() throws InterruptedException {
  4. Thread.sleep(5000);
  5. MyObject obj = new MyObject();
  6. Thread t0 = new Thread(() -> {
  7. synchronized (obj) {
  8. try {
  9. Thread.sleep(1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. System.out.println(ClassLayout.parseInstance(obj).toPrintable() + "-------------------线程1 重量级锁 结束");
  14. }
  15. });
  16. Thread t1 = new Thread(() -> {
  17. synchronized (obj) {
  18. System.out.println(ClassLayout.parseInstance(obj).toPrintable()+ "-------------------线程2 重量级锁 结束");
  19. }
  20. });
  21. t0.start();
  22. t1.start();
  23. Thread.sleep(20*1000);
  24. }
  25. }
  1. "C:\Program Files\Java\jdk1.8.0_241\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\IntelliJ IDEA 2020.1\lib\idea_rt.jar=9596:D:\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\IntelliJ IDEA 2020.1\lib\idea_rt.jar;D:\IntelliJ IDEA 2020.1\plugins\junit\lib\junit5-rt.jar;D:\IntelliJ IDEA 2020.1\plugins\junit\lib\junit-rt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\rt.jar;E:\develop\jvm\jvm-study\target\test-classes;E:\develop\jvm\jvm-study\target\classes;D:\env\maven\repo\org\springframework\boot\spring-boot-starter-web\2.3.1.RELEASE\spring-boot-starter-web-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-starter\2.3.1.RELEASE\spring-boot-starter-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot\2.3.1.RELEASE\spring-boot-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-autoconfigure\2.3.1.RELEASE\spring-boot-autoconfigure-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-starter-logging\2.3.1.RELEASE\spring-boot-starter-logging-2.3.1.RELEASE.jar;D:\env\maven\repo\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\env\maven\repo\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\env\maven\repo\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\env\maven\repo\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\env\maven\repo\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\env\maven\repo\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\env\maven\repo\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-starter-json\2.3.1.RELEASE\spring-boot-starter-json-2.3.1.RELEASE.jar;D:\env\maven\repo\com\fasterxml\jackson\core\jackson-databind\2.11.0\jackson-databind-2.11.0.jar;D:\env\maven\repo\com\fasterxml\jackson\core\jackson-core\2.11.0\jackson-core-2.11.0.jar;D:\env\maven\repo\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.0\jackson-datatype-jdk8-2.11.0.jar;D:\env\maven\repo\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.0\jackson-datatype-jsr310-2.11.0.jar;D:\env\maven\repo\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.0\jackson-module-parameter-names-2.11.0.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-starter-tomcat\2.3.1.RELEASE\spring-boot-starter-tomcat-2.3.1.RELEASE.jar;D:\env\maven\repo\org\apache\tomcat\embed\tomcat-embed-core\9.0.36\tomcat-embed-core-9.0.36.jar;D:\env\maven\repo\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;D:\env\maven\repo\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.36\tomcat-embed-websocket-9.0.36.jar;D:\env\maven\repo\org\springframework\spring-web\5.2.7.RELEASE\spring-web-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-beans\5.2.7.RELEASE\spring-beans-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-webmvc\5.2.7.RELEASE\spring-webmvc-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-aop\5.2.7.RELEASE\spring-aop-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-context\5.2.7.RELEASE\spring-context-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-expression\5.2.7.RELEASE\spring-expression-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-starter-test\2.3.1.RELEASE\spring-boot-starter-test-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-test\2.3.1.RELEASE\spring-boot-test-2.3.1.RELEASE.jar;D:\env\maven\repo\org\springframework\boot\spring-boot-test-autoconfigure\2.3.1.RELEASE\spring-boot-test-autoconfigure-2.3.1.RELEASE.jar;D:\env\maven\repo\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;D:\env\maven\repo\net\minidev\json-smart\2.3\json-smart-2.3.jar;D:\env\maven\repo\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;D:\env\maven\repo\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;D:\env\maven\repo\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\env\maven\repo\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\env\maven\repo\org\assertj\assertj-core\3.16.1\assertj-core-3.16.1.jar;D:\env\maven\repo\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;D:\env\maven\repo\org\junit\jupiter\junit-jupiter\5.6.2\junit-jupiter-5.6.2.jar;D:\env\maven\repo\org\junit\jupiter\junit-jupiter-api\5.6.2\junit-jupiter-api-5.6.2.jar;D:\env\maven\repo\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;D:\env\maven\repo\org\junit\platform\junit-platform-commons\1.6.2\junit-platform-commons-1.6.2.jar;D:\env\maven\repo\org\junit\jupiter\junit-jupiter-params\5.6.2\junit-jupiter-params-5.6.2.jar;D:\env\maven\repo\org\junit\jupiter\junit-jupiter-engine\5.6.2\junit-jupiter-engine-5.6.2.jar;D:\env\maven\repo\org\junit\vintage\junit-vintage-engine\5.6.2\junit-vintage-engine-5.6.2.jar;D:\env\maven\repo\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;D:\env\maven\repo\org\junit\platform\junit-platform-engine\1.6.2\junit-platform-engine-1.6.2.jar;D:\env\maven\repo\junit\junit\4.13\junit-4.13.jar;D:\env\maven\repo\org\mockito\mockito-core\3.3.3\mockito-core-3.3.3.jar;D:\env\maven\repo\net\bytebuddy\byte-buddy\1.10.11\byte-buddy-1.10.11.jar;D:\env\maven\repo\net\bytebuddy\byte-buddy-agent\1.10.11\byte-buddy-agent-1.10.11.jar;D:\env\maven\repo\org\objenesis\objenesis\2.6\objenesis-2.6.jar;D:\env\maven\repo\org\mockito\mockito-junit-jupiter\3.3.3\mockito-junit-jupiter-3.3.3.jar;D:\env\maven\repo\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;D:\env\maven\repo\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;D:\env\maven\repo\org\springframework\spring-core\5.2.7.RELEASE\spring-core-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-jcl\5.2.7.RELEASE\spring-jcl-5.2.7.RELEASE.jar;D:\env\maven\repo\org\springframework\spring-test\5.2.7.RELEASE\spring-test-5.2.7.RELEASE.jar;D:\env\maven\repo\org\xmlunit\xmlunit-core\2.7.0\xmlunit-core-2.7.0.jar;D:\env\maven\repo\io\springfox\springfox-swagger2\2.9.2\springfox-swagger2-2.9.2.jar;D:\env\maven\repo\io\swagger\swagger-annotations\1.5.20\swagger-annotations-1.5.20.jar;D:\env\maven\repo\io\swagger\swagger-models\1.5.20\swagger-models-1.5.20.jar;D:\env\maven\repo\com\fasterxml\jackson\core\jackson-annotations\2.11.0\jackson-annotations-2.11.0.jar;D:\env\maven\repo\io\springfox\springfox-spi\2.9.2\springfox-spi-2.9.2.jar;D:\env\maven\repo\io\springfox\springfox-core\2.9.2\springfox-core-2.9.2.jar;D:\env\maven\repo\io\springfox\springfox-schema\2.9.2\springfox-schema-2.9.2.jar;D:\env\maven\repo\io\springfox\springfox-swagger-common\2.9.2\springfox-swagger-common-2.9.2.jar;D:\env\maven\repo\io\springfox\springfox-spring-web\2.9.2\springfox-spring-web-2.9.2.jar;D:\env\maven\repo\com\google\guava\guava\20.0\guava-20.0.jar;D:\env\maven\repo\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\env\maven\repo\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;D:\env\maven\repo\org\springframework\plugin\spring-plugin-core\1.2.0.RELEASE\spring-plugin-core-1.2.0.RELEASE.jar;D:\env\maven\repo\org\springframework\plugin\spring-plugin-metadata\1.2.0.RELEASE\spring-plugin-metadata-1.2.0.RELEASE.jar;D:\env\maven\repo\org\mapstruct\mapstruct\1.2.0.Final\mapstruct-1.2.0.Final.jar;D:\env\maven\repo\io\springfox\springfox-swagger-ui\2.9.2\springfox-swagger-ui-2.9.2.jar;D:\env\maven\repo\org\openjdk\jol\jol-core\0.10\jol-core-0.10.jar;D:\env\maven\repo\org\projectlombok\lombok\1.16.10\lombok-1.16.10.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.oyb.jvm.test05.lesson09.MarkWordTest
  2. com.oyb.jvm.test03.lesson07.MyObject object internals:
  3. OFFSET SIZE TYPE DESCRIPTION VALUE
  4. 0 4 (object header) 1a 34 b3 1c (00011010 00110100 10110011 00011100) (481506330)
  5. 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
  6. 8 4 (object header) a8 dd 00 f8 (10101000 11011101 00000000 11111000) (-134160984)
  7. 12 4 (loss due to the next object alignment)
  8. Instance size: 16 bytes
  9. Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
  10. -------------------线程1 重量级锁 结束
  11. com.oyb.jvm.test03.lesson07.MyObject object internals:
  12. OFFSET SIZE TYPE DESCRIPTION VALUE
  13. 0 4 (object header) 1a 34 b3 1c (00011010 00110100 10110011 00011100) (481506330)
  14. 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
  15. 8 4 (object header) a8 dd 00 f8 (10101000 11011101 00000000 11111000) (-134160984)
  16. 12 4 (loss due to the next object alignment)
  17. Instance size: 16 bytes
  18. Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
  19. -------------------线程2 重量级锁 结束

什么是重量级锁?
自旋一直失败(达到一定程度),依然拿不到锁,就会阻塞,就会升级为重量级锁。
重量级锁依赖于操作系统的互斥量(mutext)实现的,而操作系统中线程间状态的转换需要相对比较长的时间
所以重量级锁效率很低,但被阻塞的线程不会消耗CPU。
重量级锁也是悲观锁的一种,自旋锁、轻量级锁与偏向锁属于乐观锁。

总结:

偏向锁的对象头MarkWord格式:偏向锁为0,锁类型为10
image.png