美文网首页
synchronized锁了对象后,对象头都发生了什么变化。

synchronized锁了对象后,对象头都发生了什么变化。

作者: 铁拳阿牛 | 来源:发表于2018-07-12 19:12 被阅读101次

本文代码基于jdk8 重点看代码,文字都是简介。

本文主要描述synchronized锁了对象之后,对象头发生了什么变化。

首先看看markOop.hpp 里的描述,由于本人非C++程序员,所以就不从源码上说道了。这里是描述不同位,对象的信息。亲详细看最后两位的描述。我们将会对最后两位lock信息做一个展示。

//  32 bits:
//  --------
//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//             size:32 ------------------------------------------>| (CMS free block)
//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)

然后我们继续看下面一段代码注释

//  - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
//    [ptr             | 00]  locked             ptr points to real header on stack
//    [header      | 0 | 01]  unlocked           regular object header
//    [ptr             | 10]  monitor            inflated lock (header is wapped out)
//    [ptr             | 11]  marked             used by markSweep to mark an object
//                                               not valid at any other time


整理出了最后被锁后,对象头最后两位的信息。

锁的状态 锁标志 代码里的解释
轻量级锁 00 (0) ptr points to real header on stack
重量级锁 10 inflated lock (header is wapped out)
无锁 01 (1) regular object header
GC标记状态 11 used by markSweep to mark an object not valid at any other time

然后我们开始测试,可以参照上面的信息。

import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
 *
 * @author 铁拳阿牛
 * @createTime 2018/7/12 下午5:53
 **/
public class TestSync {
    private static Unsafe unsafe;
    //为了只显示最后两位。我们不太关注对象头前面的信息。
    private static final long MOD = 3L;
    public static void main(String[] args) throws Exception {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        unsafe = (Unsafe) theUnsafe.get(Unsafe.class);
        final Object o = new Object();
        System.out.println("   这里我们只取对象头信息的锁标记位!");
        System.out.println("一 无锁 : " + Long.toBinaryString(MOD & unsafe.getLong(o, 0L)));
        lock(o);
        System.out.println("GC 标记阿牛无能未力");
    }
    public static void lock(final Object o) throws InterruptedException {
        // 轻量锁 第一次锁
        synchronized (o) {
            System.out.println("二轻量锁: " + Long.toBinaryString(MOD & unsafe.getLong(o, 0L)));
            // 锁膨胀
            syncObject(o, 100L);
            System.out.println("三重量锁: " +Long.toBinaryString(MOD & unsafe.getLong(o, 0L)));
        }
    }
    /**
     * ObjectMonitor 让锁发生膨胀
     * Thread.sleep(time);一定要有这个,不然可能Main 线程先执行。不能打印出重量锁的标记
     *
     * @param o
     * @param time
     * @throws InterruptedException
     */
    public static void syncObject(final Object o, long time) throws InterruptedException {
        new Thread(new Runnable() {
            public void run() {
                synchronized (o) {
                }
            }
        }).start();
        //让上面的线程一定先执行完
        Thread.sleep(time);
    }
}

我们拿到结果

   这里我们只取对象头信息的锁标记位!
一 无锁 : 1
二轻量锁: 0
三重量锁: 10
GC 标记阿牛无能未力
欢迎关注铁拳阿牛的公众号

相关文章

网友评论

      本文标题:synchronized锁了对象后,对象头都发生了什么变化。

      本文链接:https://www.haomeiwen.com/subject/kxirpftx.html