代码分析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结构

基本都使用64位JVM,不在对32位进行描述。Mark Word 在64位 JVM 中结构如下图所示(转自:duanmy0687):

在这里插入图片描述

2.锁升级过程

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

2.0.前言:

锁的标志为如下红框标志:
在这里插入图片描述

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

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());
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HHLUMpqj-1659494665639)(C:\Users\25060\AppData\Roaming\Typora\typora-user-images\image-20220803100852089.png)]

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();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E6NSG7rF-1659494665639)(C:\Users\25060\AppData\Roaming\Typora\typora-user-images\image-20220803101419878.png)]

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());
        }

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pZTbxfu4-1659494665639)(C:\Users\25060\AppData\Roaming\Typora\typora-user-images\image-20220803102052225.png)]

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());
        }

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8KnWsedQ-1659494665640)(C:\Users\25060\AppData\Roaming\Typora\typora-user-images\image-20220803102340737.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值