对象头的锁类型状态介绍

对象头的锁类型

在这里插入图片描述
在这里插入图片描述
简单介绍一下各部分的含义
lock: 锁状态标记位,该标记的值不同,整个mark word表示的含义不同。
biased_lock:偏向锁标记,为1时表示对象启用偏向锁,为0时表示对象没有偏向锁。

1,age:Java GC标记位对象年龄。
2,identity_hashcode:对象标识Hash码,采用延迟加载技术。当对象使用HashCode()计算后,并会将结果写到该对象头中。当对象被锁定时,该值会移动到线程Monitor中。
3,thread:持有偏向锁的线程ID和其他信息。这个线程ID并不是JVM分配的线程ID号,和Java Thread中的ID是两个概念。
4,epoch:偏向时间戳。
5,ptr_to_lock_record:指向栈中锁记录的指针。
6,ptr_to_heavyweight_monitor:指向线程Monitor的指针。

 - synchronized锁有
       1,无锁    
       2,偏向锁 偏向锁的线程id  1(是否偏向)  01 
       3,轻量级锁  指向持有锁线程栈中锁记录的指针 0(时否偏向)  01
       4,重量级锁  指向线程Monitor的指针 0(是否偏向)  10

下面的代码就是模拟锁的状态的变化,因为虚拟机加载时会延迟偏向锁的出现,所以睡5秒后就会变为偏向锁,但不偏向任何线程。
进行下面代码时你得先导入jol-core-0.9.jar,你可以区mvn仓库下载,

package com.qf1;

import org.openjdk.jol.info.ClassLayout;

public class Test3 {
    static class A{}

    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(5000);
        A a = new A();
        //初始时偏向锁,但是此时偏向id为0,谁都不偏向
        System.out.println(ClassLayout.parseInstance(a).toPrintable());
        //偏向锁,此时有偏向id,偏向main线程
        synchronized (a) {
            System.out.println("thread1 locking");
            long l = System.nanoTime();
            System.out.println(ClassLayout.parseInstance(a).toPrintable());
            long l1 = System.nanoTime();
            System.out.println((l1 - l) / 1000.0 / 1000.0);
        }
        Thread.sleep(4000);

        //轻量级锁
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("--thread3 locking--");
                    long l = System.nanoTime();
                    System.out.println(ClassLayout.parseInstance(a).toPrintable());
                    long l1 = System.nanoTime();
                    System.out.println((l1 - l) / 1000.0 / 1000.0);
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };


        //thread2,thread3 从轻量级锁-->重量级,都是重量级锁,因为它们存在竞争,锁升级
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("thread1 locking");
                    try {
                        Thread.sleep(4000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long l = System.nanoTime();
                    System.out.println(ClassLayout.parseInstance(a).toPrintable());
                    long l1 = System.nanoTime();
                    System.out.println((l1 - l) / 1000.0 / 1000.0);
                }
                try {
                    //thread1退出同步代码块,且没有死亡
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread thread3 = new Thread() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("thread2 locking");
                    long l = System.nanoTime();
                    System.out.println(ClassLayout.parseInstance(a).toPrintable());
                    long l1 = System.nanoTime();
                    System.out.println((l1 - l) / 1000.0 / 1000.0);
                }
                try {
                    //thread1退出同步代码块,且没有死亡
                    Thread.sleep(3000);
                    System.out.println("线程死亡");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        //另一个线程获取main线程获取过的锁,此时main线程还存活,造成锁  偏向main线程锁->轻量级锁
        thread1.start();

        //延时确保让上一个线程执行完
        Thread.sleep(3000);
        thread2.start();

        //让thread3延时,造成锁竞争
        Thread.sleep(2000);
        thread3.start();

    }
}

当类被加载时,对象头中的锁记录会被延迟大概4点多秒
Thread.sleep(5000);
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());这时就会变为
**1 01创建时锁类型1就代表偏向锁,但此时还没有偏向任何线程;
在这里插入图片描述

com.qf1.LRU object internals:
 OFFSET  SIZE       TYPE DESCRIPTION                   VALUE
      0     4              (object header)                05 38 6e 02 (00000101  00111000  01101110  00000010) (40777733)
      4     4              (object header)                00 00 00 00 (00000000  00000000  00000000  00000000) (0)
      8     4              (object header)                05 d6 00 f8 ( 00000101  11010110  00000000  11111000) (-134162939)

**1 01后面一大串代表偏向线程的id(不是thread.getid()的那个id)

1,什么时候变为轻量级锁呢?

 一个线程对共享对象加锁访问完毕并释放了锁后,但该线程还没结束,此时另一个线程也来对共享资源访问加锁,这时共享对象中的锁就变为轻量级锁了;0 00 

在这里插入图片描述
2,那什么时候变为重量级锁呢?

一个线程对共享对象加锁正在访问还未释放锁,此时另一个线程也来对共享资源访问加锁(等待),这时共享对象中的锁就变为重量级锁了;	

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值