代码分析sychronied和Mark Word的关系

代码分析sychronied和Mark Word的关系

在JDK1.6及之后的版本中,synchronized锁得到了优化,引入了自适应自旋锁、偏向锁、轻量锁。避免了一上来就加重量级锁,优化了锁在一定条件下的性能。

在hotspot虚拟机中,对象头主要包括两部分 MarkWord和Klass Pointer。

    MarkWord 对象标记字段,默认存储的是对象的HashCode,GC的分代年龄(2bit最大表示15)和锁的标志信息等。对于32位的虚拟机MarkWord占32bit,对于64位的虚拟机MarkWord占用64字节。 Klass Pointer Class 对象的类型指针,它指向对象对应的Class对象的内存地址。大小占4字节(指针压缩的情况下为4字节,未进行指针压缩则占8字节)。32位虚拟机MarkWord分布

1.Mark Word结构

2.锁升级过程

synchronized的锁升级过程中,锁状态升级过程为:无锁状态–> 偏向锁状态—>轻量级锁状态—>重量级锁状态。

2.0.前言:

锁的标志为如下红框标志:

偏向锁标识位 锁标识位 锁状态 存储内容 0 01 未锁定 hash code(31),年龄(4) 1 01 偏向锁 线程ID(54),时间戳(2),年龄(4) 无 00 轻量级锁 栈中锁记录的指针(64) 无 10 重量级锁 monitor的指针(64) 无 11 GC标记 空,不需要记录信息

2.1.无锁状态

当一个对象刚开始new出来时,该对象是无锁状态。此时偏向锁位为0,锁标志位01。

import org.openjdk.jol.info.ClassLayout;
/**
 * @Author tangjunjie
 * @Date 2022/8/3 9:54
 * @PackageName:面试
 * @ClassName: Test
 * @Description: TODO
 * @Version 1.0
 */
public class Test {
          
   
    public static void main(String[] args) {
          
   
        Test test = new Test();
        System.out.println(ClassLayout.parseInstance(test).toPrintable());
    }
}

2.2.升级为偏向锁状态

如果有线程上锁:指的就是把markword的线程ID改为自己线程ID的过程。

public class Test2 {
          
   
    public static void main(String[] args) {
          
   
        Test test = new Test();
        new Thread(()->{
          
   
            synchronized(test){
          
   
                System.out.println(ClassLayout.parseInstance(test).toPrintable());
            }
        }).start();
    }
}

2.3.升级为轻量级锁状态

如果有线程竞争:撤销偏向锁,升级轻量级锁。线程在自己的线程栈生成LockRecord,用CAS操作将markword设置为指向自己这个线程的LockRecord的指针,设置成功者得到锁。

public class Test3 {
          
   
    public static void main(String[] args) throws InterruptedException {
          
   
        Test test = new Test();
        Thread thread =  new Thread(()->{
          
   
            synchronized (test) {
          
   
                System.out.println(ClassLayout.parseInstance(test).toPrintable());
            }
        });
        thread.start();
        //等待thread
        thread.join();
        synchronized (test) {
          
   
            System.out.println(ClassLayout.parseInstance(test).toPrintable());
        }

    }
}

2.4.升级为重量级锁状态

如果竞争加剧     竞争加剧:有线程超过10次自旋, -XX:PreBlockSpin,或者自旋线程数超过CPU核树的一半,1.6之后,加入自适应自旋adapative self spinning,JVM自己控制;     升级重量级锁: 向操作系统升级资源,等待操作系统的调度,然后再映射会用户空间;

public class Test3 {
          
   
    public static void main(String[] args) throws InterruptedException {
          
   
        Test test = new Test();
        Thread thread =  new Thread(()->{
          
   
            synchronized (test) {
          
   
                System.out.println(ClassLayout.parseInstance(test).toPrintable());
            }
        });
        thread.start();
        //等待thread
        //thread.join();
        synchronized (test) {
          
   
            System.out.println(ClassLayout.parseInstance(test).toPrintable());
        }

    }
}
经验分享 程序员 微信小程序 职场和发展