java并发编程(八)synchronized原理之偏向锁

346 阅读58分钟

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

偏向锁的引入,对轻量级锁的CAS操作进行了优化。轻量级锁需要每次都是用CAS来尝试获取锁,占用CPU时间。

jdk1.6中引入偏向锁后,只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现这个线程 ID 是自己的就表示没有竞争,不用重新 CAS。以后只要不发生竞争,这个对象就归该线程所有。

一、偏向锁的状态

|----------------------------------------------------------------------------------------------|
|                                   Mark Word(64bits)                     |      State         |
|----------------------------------------------------------------------------------------------|
|    unused:25|identity_hashcode:31|unused:1|age:4|biase_lock:0| lock:01  |      Nomal         |
|----------------------------------------------------------------------------------------------|
|    thread:54|      epoch:2       |unused:1|age:4|biase_lock:1| lock:01  |      Biased        |
|----------------------------------------------------------------------------------------------|
|                        ptr_to_lock_record:62                 | lock:00  | Lightweight Locked |
|----------------------------------------------------------------------------------------------|
|                       ptr_to_heavyweight_monitor:62          | lock:10  | Heavyweight Locked |
|----------------------------------------------------------------------------------------------|
|                                                              | lock:11  |    Marked for GC   |
|----------------------------------------------------------------------------------------------|

如上表所示,偏向锁的状态biase_lock是1,lock是01。

下面我们借用jol工具看下状态:

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>

1.1 默认情况下的偏向锁

引入依赖后,有如下代码:

    public static void main(String[] args)  {

        Object lock = new Object();

        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

结果:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   8        (object header: class)    0x000000001be01c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

我们只关注上述结果的mark word 部分,后面的括号当中的内容是non-biasable,就是没开启偏向锁。并且value的值是001结尾,对照上面的Mark Word 状态表的后三位,刚好是无锁状态,0,01。

此处有一个问题,偏向锁是延时的,在刚启动的时候并没有开启,我们可以使用以下参数设置立即生效:

 -XX:BiasedLockingStartupDelay=0

设置完参数后再次启动的结果如下,发现16进制的value是5,转为2进制就是101,是上表中偏向锁状态的后三位,并且括号内的内容变成了biasable,具有了偏向锁的能力:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x000000001c0a1c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
  • 总结:
    • 偏向锁是默认开启的,但是是延时的,需要通过参数**-XX:BiasedLockingStartupDelay=0**禁用延时。
    • 对象在创建后,如果开启了偏向锁,thread、epoch、age 都为 0。
    • 对象在创建后,如果没有开启偏向锁,hashcode、age 都为 0。
    • 禁用偏向锁,使用**-XX:-UseBiasedLocking**参数。

1.2 线程持有偏向锁

1.2.1 单线程持有

当有线程持有上述偏向锁,那么对象头的Mark Word 会有什么变化呢? 代码如下:

    public static void main(String[] args) {

        Object lock = new Object();

        System.out.println(ClassLayout.parseInstance(lock).toPrintable());

        synchronized (lock) {
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        }

        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

在锁被持有前,持有中,持有后的状态分别如下:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x000000001c081c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000000320a005 (biased: 0x000000000000c828; epoch: 0; age: 0)
  8   8        (object header: class)    0x000000001c081c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000000320a005 (biased: 0x000000000000c828; epoch: 0; age: 0)
  8   8        (object header: class)    0x000000001c081c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

如上所示,当锁被线程持有后,mark word的内容发生了变化。其中value是8字节的全部内容,末尾是005,转化成2进制就是101,确实是使用的偏向锁。在括号内的biased表示偏向锁在哪个线程上,后面的16进制数,就是线程的id。

在锁被释放后,当前对象仍然是持有该偏向锁的。

1.2.2 两个线程竞争

有如下代码,使用main方法的主线程和一个Thread模仿一个锁竞争的情况,看看对象头是如何变化的。

    public static void main(String[] args) throws InterruptedException {

        Object lock = new Object();
        // 打印初始状态
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());

        synchronized (lock) {
            // 打印偏向锁状态
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
            TimeUnit.SECONDS.sleep(2);
        }

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            synchronized (lock){
                // 打印轻量级锁
                System.out.println(ClassLayout.parseInstance(lock).toPrintable());
            }
        }).start();

        TimeUnit.SECONDS.sleep(1);
        // 打印无锁
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

结果如下所示:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x000000001bbd1c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000002e1a005 (biased: 0x000000000000b868; epoch: 0; age: 0)
  8   8        (object header: class)    0x000000001bbd1c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000020b5efe0 (thin lock: 0x0000000020b5efe0)
  8   8        (object header: class)    0x000000001bbd1c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   8        (object header: class)    0x000000001bbd1c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

过程分析:

  • 新创建对象,开启偏向锁
  • 当主线程获取锁后,独自持有偏向锁,阻塞2s
  • 一秒后,另一个线程来竞争此锁,此时因为主线程在阻塞,所以此线程升级成了轻量级锁,如上结果thin lock表示轻量级锁,后面的16进制数表示持有锁的线程id。
  • 当主线程再次休息一秒,同步代码块执行完毕,此时释放锁,所以最终变成了无锁状态non-biasable

1.2.3 多个线程竞争

使用5个线程竞争:

    public static void main(String[] args) throws InterruptedException {

        Object lock = new Object();
        // 打印初始状态
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());

        synchronized (lock) {
            // 打印偏向锁状态
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
            TimeUnit.SECONDS.sleep(2);
        }

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            synchronized (lock) {
                // 打印轻量级锁
                System.out.println(ClassLayout.parseInstance(lock).toPrintable());
            }
        }).start();

        TimeUnit.SECONDS.sleep(1);

        // 5个线程竞争
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                synchronized (lock) {
                    // 打印轻量级锁
                    System.out.println(ClassLayout.parseInstance(lock).toPrintable());
                }
            }).start();
        }

        TimeUnit.SECONDS.sleep(1);
        // 打印无锁
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

结果如下所示:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000002ada005 (biased: 0x000000000000ab68; epoch: 0; age: 0)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x00000000208df7f0 (thin lock: 0x00000000208df7f0)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000001c33a60a (fat lock: 0x000000001c33a60a)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000001c33a60a (fat lock: 0x000000001c33a60a)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000001c33a60a (fat lock: 0x000000001c33a60a)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000001c33a60a (fat lock: 0x000000001c33a60a)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000001c33a60a (fat lock: 0x000000001c33a60a)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   8        (object header: class)    0x000000001b941c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

前面的过程,与上一小节的测试结果没有不同,不同处在于后面的循环创建的5个线程,此时打印的对象头内容是fat lock,表示重量级锁,其后面跟着的16进制数表示Monitor的地址,多个线程竞争时,未获取到锁的线程将会添加到Monitor的EntryList当中,等待唤醒。

二、锁撤销

2.1 hashcode

在创建对象的时候,hashcode是0,只有当调用该对象后,hashcode才被赋值,如下代码所示:

    public static void main(String[] args) throws InterruptedException {

        Object lock = new Object();
        // 打印初始状态
        System.out.println(lock);
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

结果如下:

java.lang.Object@16f65612
java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x00000016f6561201 (hash: 0x16f65612; age: 0)
  8   8        (object header: class)    0x000000001c051c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
  • 轻量级锁会在锁记录中记录 hashCode
  • 重量级锁会在 Monitor 中记录 hashCode

调用对象的hashcode()方法,会使对象的偏向锁被撤销:

    public static void main(String[] args) throws InterruptedException {

        Object lock = new Object();
        // 打印初始状态
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());


        synchronized (lock) {
            // 打印偏向锁状态
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        }

        //调用hashcode
        lock.hashCode();
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());

        //再次获取锁
        synchronized (lock) {
            // 打印偏向锁状态
            System.out.println(ClassLayout.parseInstance(lock).toPrintable());
        }
    }

结果:

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x000000001be21c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000000305a005 (biased: 0x000000000000c168; epoch: 0; age: 0)
  8   8        (object header: class)    0x000000001be21c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000002ed94a8b01 (hash: 0x2ed94a8b; age: 0)
  8   8        (object header: class)    0x000000001be21c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

java.lang.Object object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000002faf730 (thin lock: 0x0000000002faf730)
  8   8        (object header: class)    0x000000001be21c00
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

如上所示:发现调用hashcode后,对象头打印出了hash值,并且将value的值转换成二进制后得到后三位的结果是001,001表示无锁的正常状态。

当再次尝试获取锁的时候,发现获取到的只能是轻量级锁(thin lock)了。

2.2 偏向锁锁撤销 - 升级轻量级锁或重量级锁

这里就是前面偏向锁状态当中,当有多个线程竞争锁的时候,无论是升级成轻量级锁,还是重量级锁,在最终将锁释放后,都会变成无锁状态, 即偏向锁的状态被撤销了。

2.3 重偏向优化

如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程 T1 的对象仍有机会重新偏向 T2,重偏向会重置对象的 Thread ID。

当撤销偏向锁阈值超过 14 次后(这个次数在我的电脑时14,有些人似乎20,暂时不知道怎么设定的),jvm 会这样觉得,我是不是偏向错了呢,于是会在给这些对象加锁时重新偏向至加锁线程。

如下所示,有两个线程,t1组装一个大小为30的集合,结合内创建30个对象。t2在t1处理数据时,通过wait等待,当t1通过notify唤醒t2时,t2开始占有锁(30个对象,每一个都有自己的锁):

    public static void main(String[] args) {
        test3();
    }

    public static String print(String s) {
        String[] split = s.split("\r\n");
        return split[2].substring(41);
    }

    private static void test3() {
        Vector<Object> list = new Vector<>();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                Object d = new Object();
                list.add(d);
                synchronized (d) {
                    System.out.println(i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                }
            }
            synchronized (list) {
                list.notify();
            }
        }, "t1");
        t1.start();

        Thread t2 = new Thread(() -> {
            synchronized (list) {
                try {
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("===============> ");
            for (int i = 0; i < 30; i++) {
                Object d = list.get(i);
                System.out.println(i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                synchronized (d) {
                    System.out.println(i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                }
                System.out.println(i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
            }
        }, "t2");
        t2.start();
    }

结果:

0	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
1	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
2	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
3	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
4	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
5	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
6	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
7	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
8	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
9	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
10	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
11	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
12	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
13	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
14	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
15	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
16	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
17	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
18	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
19	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
20	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
21	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
22	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
23	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
24	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
25	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
26	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
27	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
28	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
29	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
===============> 
0	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
0	0x00000000210df370 (thin lock: 0x00000000210df370)
0	0x0000000000000001 (non-biasable; age: 0)
1	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
1	0x00000000210df370 (thin lock: 0x00000000210df370)
1	0x0000000000000001 (non-biasable; age: 0)
2	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
2	0x00000000210df370 (thin lock: 0x00000000210df370)
2	0x0000000000000001 (non-biasable; age: 0)
3	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
3	0x00000000210df370 (thin lock: 0x00000000210df370)
3	0x0000000000000001 (non-biasable; age: 0)
4	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
4	0x00000000210df370 (thin lock: 0x00000000210df370)
4	0x0000000000000001 (non-biasable; age: 0)
5	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
5	0x00000000210df370 (thin lock: 0x00000000210df370)
5	0x0000000000000001 (non-biasable; age: 0)
6	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
6	0x00000000210df370 (thin lock: 0x00000000210df370)
6	0x0000000000000001 (non-biasable; age: 0)
7	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
7	0x00000000210df370 (thin lock: 0x00000000210df370)
7	0x0000000000000001 (non-biasable; age: 0)
8	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
8	0x00000000210df370 (thin lock: 0x00000000210df370)
8	0x0000000000000001 (non-biasable; age: 0)
9	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
9	0x00000000210df370 (thin lock: 0x00000000210df370)
9	0x0000000000000001 (non-biasable; age: 0)
10	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
10	0x00000000210df370 (thin lock: 0x00000000210df370)
10	0x0000000000000001 (non-biasable; age: 0)
11	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
11	0x00000000210df370 (thin lock: 0x00000000210df370)
11	0x0000000000000001 (non-biasable; age: 0)
12	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
12	0x00000000210df370 (thin lock: 0x00000000210df370)
12	0x0000000000000001 (non-biasable; age: 0)
13	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
13	0x00000000210df370 (thin lock: 0x00000000210df370)
13	0x0000000000000001 (non-biasable; age: 0)
14	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
14	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
14	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
15	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
15	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
15	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
16	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
16	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
16	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
17	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
17	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
17	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
18	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
18	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
18	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
19	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
19	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
19	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
20	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
20	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
20	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
21	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
21	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
21	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
22	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
22	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
22	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
23	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
23	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
23	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
24	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
24	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
24	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
25	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
25	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
25	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
26	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
26	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
26	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
27	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
27	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
27	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
28	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
28	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
28	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
29	0x0000000020066805 (biased: 0x000000000008019a; epoch: 0; age: 0)
29	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
29	0x0000000020067905 (biased: 0x000000000008019e; epoch: 0; age: 0)
  • ===============>之前的30个对象,都是偏向于0x000000000008019e这个线程(t1)。
  • ===============>之后开始进行了锁升级,升级成了轻量级锁(thin lock),释放后变成无锁状态(non-biasable)。
  • 在经历14次锁升级,锁撤销后,发现第15次不在进行此类操作,而是直接修改偏向线程的id了。

因为锁升级和锁撤销会带来一定的性能损耗,所以jvm在这方面做了重偏向的优化。

2.4 批量锁撤销

当撤销偏向锁阈值超过 14 次后,jvm 会这样觉得,自己确实偏向错了,根本就不该偏向。于是整个类的所有对象都会变为不可偏向的,新建的对象也是不可偏向的。

使用三个线程,初始化一个50个对象的集合,t1处理数据,唤醒t2;t2处理完数据唤醒t3;代码如下:

    static Thread t1, t2, t3;

    public static void main(String[] args) throws InterruptedException {
        test3();
    }

    public static String print(String s) {
        String[] split = s.split("\r\n");
        return split[2].substring(41);
    }

    private static void test3() throws InterruptedException {
        Vector<Object> list = new Vector<>();
        t1 = new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                Object d = new Object();
                list.add(d);
                synchronized (d) {
                    System.out.println(i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                }
            }
            LockSupport.unpark(t2);
        }, "t1");
        t1.start();

        t2 = new Thread(() -> {
            LockSupport.park();
            System.out.println("=========第二阶段======> ");
            for (int i = 0; i < 50; i++) {
                Object d = list.get(i);
                System.out.println("t2: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                synchronized (d) {
                    System.out.println("t2: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                }
                System.out.println("t2: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
            }
            LockSupport.unpark(t3);
        }, "t2");
        t2.start();


        t3 = new Thread(() -> {
            LockSupport.park();
            System.out.println("=========第三阶段======>");
            for (int i = 0; i < 50; i++) {
                Object d = list.get(i);
                System.out.println("t3: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                synchronized (d) {
                    System.out.println("t3: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
                }
                System.out.println("t3: " + i + "\t" + print(ClassLayout.parseInstance(d).toPrintable()));
            }
        }, "t3");
        t3.start();

        t3.join();
        // 输出一个新的对象的对象头,发现是不可偏向锁
        System.out.println(print(ClassLayout.parseInstance(new Object()).toPrintable()));
    }

结果:

0	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
1	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
2	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
3	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
4	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
5	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
6	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
7	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
8	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
9	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
10	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
11	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
12	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
13	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
14	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
15	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
16	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
17	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
18	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
19	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
20	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
21	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
22	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
23	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
24	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
25	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
26	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
27	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
28	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
29	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
30	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
31	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
32	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
33	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
34	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
35	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
36	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
37	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
38	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
39	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
40	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
41	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
42	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
43	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
44	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
45	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
46	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
47	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
48	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
49	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
=========第二阶段======> 
t2: 0	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 0	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 0	0x0000000000000001 (non-biasable; age: 0)
t2: 1	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 1	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 1	0x0000000000000001 (non-biasable; age: 0)
t2: 2	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 2	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 2	0x0000000000000001 (non-biasable; age: 0)
t2: 3	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 3	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 3	0x0000000000000001 (non-biasable; age: 0)
t2: 4	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 4	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 4	0x0000000000000001 (non-biasable; age: 0)
t2: 5	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 5	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 5	0x0000000000000001 (non-biasable; age: 0)
t2: 6	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 6	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 6	0x0000000000000001 (non-biasable; age: 0)
t2: 7	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 7	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 7	0x0000000000000001 (non-biasable; age: 0)
t2: 8	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 8	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 8	0x0000000000000001 (non-biasable; age: 0)
t2: 9	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 9	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 9	0x0000000000000001 (non-biasable; age: 0)
t2: 10	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 10	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 10	0x0000000000000001 (non-biasable; age: 0)
t2: 11	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 11	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 11	0x0000000000000001 (non-biasable; age: 0)
t2: 12	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 12	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 12	0x0000000000000001 (non-biasable; age: 0)
t2: 13	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 13	0x000000002130f160 (thin lock: 0x000000002130f160)
t2: 13	0x0000000000000001 (non-biasable; age: 0)
t2: 14	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 14	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 14	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 15	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 15	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 15	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 16	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 16	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 16	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 17	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 17	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 17	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 18	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 18	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 18	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 19	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 19	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 19	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 20	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 20	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 20	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 21	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 21	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 21	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 22	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 22	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 22	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 23	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 23	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 23	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 24	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 24	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 24	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 25	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 25	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 25	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 26	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 26	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 26	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 27	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 27	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 27	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 28	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 28	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 28	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 29	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 29	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 29	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 30	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 30	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 30	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 31	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 31	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 31	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 32	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 32	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 32	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 33	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 33	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 33	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 34	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 34	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 34	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 35	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 35	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 35	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 36	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 36	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 36	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 37	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 37	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 37	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 38	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 38	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 38	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 39	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 39	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 39	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 40	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 40	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 40	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 41	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 41	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 41	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 42	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 42	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 42	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 43	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 43	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 43	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 44	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 44	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 44	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 45	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 45	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 45	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 46	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 46	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 46	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 47	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 47	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 47	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 48	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 48	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 48	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 49	0x00000000202aa005 (biased: 0x0000000000080aa8; epoch: 0; age: 0)
t2: 49	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t2: 49	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
=========第三阶段======>
t3: 0	0x0000000000000001 (non-biasable; age: 0)
t3: 0	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 0	0x0000000000000001 (non-biasable; age: 0)
t3: 1	0x0000000000000001 (non-biasable; age: 0)
t3: 1	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 1	0x0000000000000001 (non-biasable; age: 0)
t3: 2	0x0000000000000001 (non-biasable; age: 0)
t3: 2	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 2	0x0000000000000001 (non-biasable; age: 0)
t3: 3	0x0000000000000001 (non-biasable; age: 0)
t3: 3	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 3	0x0000000000000001 (non-biasable; age: 0)
t3: 4	0x0000000000000001 (non-biasable; age: 0)
t3: 4	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 4	0x0000000000000001 (non-biasable; age: 0)
t3: 5	0x0000000000000001 (non-biasable; age: 0)
t3: 5	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 5	0x0000000000000001 (non-biasable; age: 0)
t3: 6	0x0000000000000001 (non-biasable; age: 0)
t3: 6	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 6	0x0000000000000001 (non-biasable; age: 0)
t3: 7	0x0000000000000001 (non-biasable; age: 0)
t3: 7	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 7	0x0000000000000001 (non-biasable; age: 0)
t3: 8	0x0000000000000001 (non-biasable; age: 0)
t3: 8	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 8	0x0000000000000001 (non-biasable; age: 0)
t3: 9	0x0000000000000001 (non-biasable; age: 0)
t3: 9	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 9	0x0000000000000001 (non-biasable; age: 0)
t3: 10	0x0000000000000001 (non-biasable; age: 0)
t3: 10	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 10	0x0000000000000001 (non-biasable; age: 0)
t3: 11	0x0000000000000001 (non-biasable; age: 0)
t3: 11	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 11	0x0000000000000001 (non-biasable; age: 0)
t3: 12	0x0000000000000001 (non-biasable; age: 0)
t3: 12	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 12	0x0000000000000001 (non-biasable; age: 0)
t3: 13	0x0000000000000001 (non-biasable; age: 0)
t3: 13	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 13	0x0000000000000001 (non-biasable; age: 0)
t3: 14	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 14	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 14	0x0000000000000001 (non-biasable; age: 0)
t3: 15	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 15	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 15	0x0000000000000001 (non-biasable; age: 0)
t3: 16	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 16	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 16	0x0000000000000001 (non-biasable; age: 0)
t3: 17	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 17	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 17	0x0000000000000001 (non-biasable; age: 0)
t3: 18	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 18	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 18	0x0000000000000001 (non-biasable; age: 0)
t3: 19	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 19	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 19	0x0000000000000001 (non-biasable; age: 0)
t3: 20	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 20	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 20	0x0000000000000001 (non-biasable; age: 0)
t3: 21	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 21	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 21	0x0000000000000001 (non-biasable; age: 0)
t3: 22	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 22	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 22	0x0000000000000001 (non-biasable; age: 0)
t3: 23	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 23	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 23	0x0000000000000001 (non-biasable; age: 0)
t3: 24	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 24	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 24	0x0000000000000001 (non-biasable; age: 0)
t3: 25	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 25	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 25	0x0000000000000001 (non-biasable; age: 0)
t3: 26	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 26	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 26	0x0000000000000001 (non-biasable; age: 0)
t3: 27	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 27	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 27	0x0000000000000001 (non-biasable; age: 0)
t3: 28	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 28	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 28	0x0000000000000001 (non-biasable; age: 0)
t3: 29	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 29	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 29	0x0000000000000001 (non-biasable; age: 0)
t3: 30	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 30	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 30	0x0000000000000001 (non-biasable; age: 0)
t3: 31	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 31	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 31	0x0000000000000001 (non-biasable; age: 0)
t3: 32	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 32	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 32	0x0000000000000001 (non-biasable; age: 0)
t3: 33	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 33	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 33	0x0000000000000001 (non-biasable; age: 0)
t3: 34	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 34	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 34	0x0000000000000001 (non-biasable; age: 0)
t3: 35	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 35	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 35	0x0000000000000001 (non-biasable; age: 0)
t3: 36	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 36	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 36	0x0000000000000001 (non-biasable; age: 0)
t3: 37	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 37	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 37	0x0000000000000001 (non-biasable; age: 0)
t3: 38	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 38	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 38	0x0000000000000001 (non-biasable; age: 0)
t3: 39	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 39	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 39	0x0000000000000001 (non-biasable; age: 0)
t3: 40	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 40	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 40	0x0000000000000001 (non-biasable; age: 0)
t3: 41	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 41	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 41	0x0000000000000001 (non-biasable; age: 0)
t3: 42	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 42	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 42	0x0000000000000001 (non-biasable; age: 0)
t3: 43	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 43	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 43	0x0000000000000001 (non-biasable; age: 0)
t3: 44	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 44	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 44	0x0000000000000001 (non-biasable; age: 0)
t3: 45	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 45	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 45	0x0000000000000001 (non-biasable; age: 0)
t3: 46	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 46	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 46	0x0000000000000001 (non-biasable; age: 0)
t3: 47	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 47	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 47	0x0000000000000001 (non-biasable; age: 0)
t3: 48	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 48	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 48	0x0000000000000001 (non-biasable; age: 0)
t3: 49	0x00000000202aa905 (biased: 0x0000000000080aaa; epoch: 0; age: 0)
t3: 49	0x000000002140f690 (thin lock: 0x000000002140f690)
t3: 49	0x0000000000000001 (non-biasable; age: 0)
0x0000000000000001 (non-biasable; age: 0)
  • 第二阶段其实就是前一章节讲的重偏向优化
  • 第三阶段开始,线程t3加入进来,前14个对象在第二阶段已经被撤销了偏向锁,所以这14个对象要不停的经历轻量级锁到锁撤销的状态。
  • 当第三阶段达到第15次时,这之后的对象都是偏向于线程t2的,需要经历锁撤销,轻量级锁的过程,到结束并没有进行一个所偏向的优化了。
  • 注意最后一行,当再次打印一个新创建的对象头时,发现是不可使用偏向锁的(关于这个阈值,有人说是40,我没有测试过)。