栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA 偏向锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA 偏向锁

学习java的偏向锁,想用代码演示一下,结果被自动装箱坑了,记录一下

一、-128~127
    @Test
    public void test0() {
        sleep(5);
        Integer i = 1;
        //无偏向
        System.out.println(ClassLayout.parseInstance(i).toPrintable());
    }

打印如下

java.lang.Integer object internals:
 OFFSET  SIZE   TYPE DEscriptION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           67 22 00 f8 (01100111 00100010 00000000 11111000) (-134208921)
     12     4    int Integer.value                             1
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
二、Not In -128~127
    @Test
    public void test1() {
        sleep(5);
        Integer i = 555;
        //有偏向
        System.out.println(ClassLayout.parseInstance(i).toPrintable());
    }

打印结果如下

java.lang.Integer object internals:
 OFFSET  SIZE   TYPE DEscriptION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           67 22 00 f8 (01100111 00100010 00000000 11111000) (-134208921)
     12     4    int Integer.value                             555
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
三、JVM启动,前4秒创建的对象无偏向锁
    @Test
    public void test2() {
        Integer i = 555;
        sleep(5);
        //无偏向
        System.out.println(ClassLayout.parseInstance(i).toPrintable());
    }

打印结果如下

java.lang.Integer object internals:
 OFFSET  SIZE   TYPE DEscriptION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           67 22 00 f8 (01100111 00100010 00000000 11111000) (-134208921)
     12     4    int Integer.value                             555
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
四、偏向锁的实践
    static class Foo {
        private int i;
        public synchronized void incr(String msg) {
            i++;
            System.out.println(msg + "<" + Thread.currentThread().getName() + ">ttt" + ClassLayout.parseInstance(this).toPrintable());
        }
    }

    @Test
    public void test11() throws InterruptedException {
        sleep(5);
        Foo foo = new Foo();
        System.err.println("初始状态t" + ClassLayout.parseInstance(foo).toPrintable());
        foo.incr("此时已经偏向main线程了");
        System.err.println("此时没有线程竞争锁,但mark word不改变,main线程id依然存在t" + ClassLayout.parseInstance(foo).toPrintable());
        foo.incr("main线程继续获取锁,识别到是自己的线程id则直接进入锁");

        Thread thread = new Thread(() -> foo.incr("此时第二个线程尝试获取锁"));
        thread.start();
        thread.join();
        System.err.println("由上可知,只要有第二个线程尝试获取锁,[偏向锁]都会升级为[轻量级锁],而不是把mark word里的线程id改成第二个线程的;" +
                "(理解偏向锁:只要有线程得到了偏向锁,那么这个锁一直归该线程所有,如果有其他线程竞争,立刻升级轻量级锁)");
        System.err.println("锁居然释放了t" + ClassLayout.parseInstance(foo).toPrintable());
        foo.incr("锁释放后再获取锁,001->000轻量级锁");
    }

打印结果如下

初始状态	com.preon.demo.SynchronizedTest2$Foo object internals:
 OFFSET  SIZE   TYPE DEscriptION                               VALUE
      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940)
     12     4    int Foo.i                                     0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

此时已经偏向main线程了
com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) 05 30 c8 02 (00000101 00110000 11001000 00000010) (46673925) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 1 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total 此时没有线程竞争锁,但mark word不改变,main线程id依然存在 com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) 05 30 c8 02 (00000101 00110000 11001000 00000010) (46673925) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 1 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total main线程继续获取锁,识别到是自己的线程id则直接进入锁
com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) 05 30 c8 02 (00000101 00110000 11001000 00000010) (46673925) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 2 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total 此时第二个线程尝试获取锁 com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) c0 f2 e8 22 (11000000 11110010 11101000 00100010) (585691840) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 3 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total 由上可知,只要有第二个线程尝试获取锁,[偏向锁]都会升级为[轻量级锁],而不是把mark word里的线程id改成第二个线程的;(理解偏向锁:只要有线程得到了偏向锁,那么这个锁一直归该线程所有,如果有其他线程竞争,立刻升级轻量级锁) 锁居然释放了 com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 3 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total 锁释放后再获取锁,001->000轻量级锁
com.preon.demo.SynchronizedTest2$Foo object internals: OFFSET SIZE TYPE DEscriptION VALUE 0 4 (object header) e0 e3 c7 02 (11100000 11100011 11000111 00000010) (46654432) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 24 24 01 f8 (00100100 00100100 00000001 11111000) (-134142940) 12 4 int Foo.i 4 Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

未完待续…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/686595.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号