synchronized锁升级过程

178 阅读8分钟

流程图

1.jpg

对象锁标志

锁状态偏向锁锁的标志位
无锁001
偏向锁101
轻量级锁00
重量级锁10
  1. 无状态-->偏向锁
  2. 无状态-->轻量级锁
  3. 偏向锁-->轻量级锁
  4. 轻量级锁-->重量级锁

代码测试

用到的jar包

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>
import org.openjdk.jol.info.ClassLayout;

public class sync3 {
    public static void main(String[] args) throws InterruptedException {
        // jvm默认延时4s创建的对象都自动开启偏向锁
        // 1. 无状态-->偏向锁
        final User user1 = new User();
        Thread.sleep(5000);
        final User user2 = new User();

        System.out.println("jvm一开始就创建的对象,是无状态001: " + ClassLayout.parseInstance(user1).toPrintable());
        System.out.println("jvm开始4s后创建的对象,是偏向锁101: " + ClassLayout.parseInstance(user2).toPrintable());

        System.out.println("******************************************\n");
        2. 无状态-->轻量级锁
        synchronized (user1){
            System.out.println("无状态->轻量级锁00(带线程id): " + ClassLayout.parseInstance(user1).toPrintable());
        }
        System.out.println("无状态01(带线程id): " + ClassLayout.parseInstance(user1).toPrintable());
        synchronized (user2){
            System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());
        }
        System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());

        System.out.println("******************************************\n");

        synchronized (user2) {
            System.out.println("偏向锁101(带线程id): " + ClassLayout.parseInstance(user2).toPrintable());
        }

        System.out.println("******************************************\n");
        
        // 线程加锁,锁升级
        // 3. 偏向锁-->轻量级锁
        new Thread(() -> {
            synchronized (user2){
                System.out.println("轻量级锁00: " + ClassLayout.parseInstance(user2).toPrintable());
                try{
                    Thread.sleep(3000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println("轻量级->重量级10: " + ClassLayout.parseInstance(user2).toPrintable());
            }
        }).start();

        Thread.sleep(1000);

        // 在上一个线程还未完成,加入另外一个线程加入锁的抢占,导致锁再次升级
        // 4. 轻量级锁-->重量级锁
        new Thread(() -> {
            synchronized (user2){
                System.out.println("重量级10: " + ClassLayout.parseInstance(user2).toPrintable());
            }
        }).start();
    }
}

2.jpg
红色标记是锁的标志位
结果:

jvm一开始就创建的对象,是无状态001: com.company.Thread.Concurrent.User 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)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

jvm开始4s后创建的对象,是偏向锁101: com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

******************************************

无状态->轻量级锁00(带线程id): com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           50 f7 cd 02 (01010000 11110111 11001101 00000010) (47052624)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

无状态01(带线程id): com.company.Thread.Concurrent.User 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)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

******************************************

偏向锁101(带线程id): com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 28 de 02 (00000101 00101000 11011110 00000010) (48113669)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

******************************************

轻量级锁00: com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           98 f1 3f 1b (10011000 11110001 00111111 00011011) (457175448)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

sleep 3s

轻量级->重量级10: com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           3a 98 ed 02 (00111010 10011000 11101101 00000010) (49125434)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

重量级10: com.company.Thread.Concurrent.User object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           3a 98 ed 02 (00111010 10011000 11101101 00000010) (49125434)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           43 c1 00 20 (01000011 11000001 00000000 00100000) (536920387)
     12     4   java.lang.String User.id                                   null
     16     4   java.lang.String User.name                                 null
     20     4                    (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

以上就是锁升级的基本过程。