zoukankan      html  css  js  c++  java
  • 偏向锁是个什么东东?

      上次我们说了对象头是个什么东东?,但是从我们跑的代码输出却看不到偏向锁这个东东。为啥对象实例化出来之后,对象头里是不支持偏向的呢?其实是JVM搞的鬼,JVM虽然默认启用偏向锁,但启动后4秒内并不支持。可以通过-XX:BiasedLockingStartupDelay=0参数将JVM启动后支持偏向锁的延迟时间设置为0,这样就可以看到偏向锁的输出了:

      代码也改动一下:

    import com.wlf.springcloudgateway.javabean.HelloWorld;
    import org.openjdk.jol.info.ClassLayout;
    
    import java.util.concurrent.TimeUnit;
    
    public class ObjectMarkWord {
    
        public static void main(String[] args) throws InterruptedException {
    
    //        TimeUnit.SECONDS.sleep(5); // 启用偏向锁,要么开启jvm参数-XX:BiasedLockingStartupDelay=0,要么等待5秒
    
            // 实例化对象
            HelloWorld helloWorld = HelloWorld.builder().name("wlf").build();
    
            // 1、普通对象,无锁
            System.out.println("无锁,可偏向:");
            printfObjMarkWord(helloWorld);
    
            // 2、单线程首次加锁,偏向锁
            System.out.println("偏向锁:");
            new Thread(() -> {
                System.out.println("首次偏向:");
                synchronized (helloWorld) {
                    printfObjMarkWord(helloWorld);
                }
    
                System.out.println("第二次,重偏向:");
                synchronized (helloWorld) {
                    printfObjMarkWord(helloWorld);
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            TimeUnit.SECONDS.sleep(1);
    
            // 3、多个线程加锁,膨胀为重量锁
            System.out.println("重量锁:");
            for (int i = 0; i < 2; i++) {
                new Thread(() -> {
                    synchronized (helloWorld) {
                        printfObjMarkWord(helloWorld);
                    }
                }).start();
            }
        }
    
        private static void printfObjMarkWord(Object obj) {
            System.out.println("-------------------------");
            System.out.println(ClassLayout.parseInstance(obj).toPrintable());
            System.out.println("-------------------------");
    
        }
    
    }

      输出结果:

    无锁,可偏向:
    -------------------------
    # WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
    com.wlf.springcloudgateway.javabean.HelloWorld 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)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
         12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         16     8   java.lang.String HelloWorld.name                           (object)
    Instance size: 24 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -------------------------
    偏向锁:
    首次偏向:
    -------------------------
    com.wlf.springcloudgateway.javabean.HelloWorld object internals:
     OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
          0     4                    (object header)                           05 00 93 19 (00000101 00000000 10010011 00011001) (429064197)
          4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
          8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
         12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         16     8   java.lang.String HelloWorld.name                           (object)
    Instance size: 24 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -------------------------
    第二次,重偏向:
    -------------------------
    com.wlf.springcloudgateway.javabean.HelloWorld object internals:
     OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
          0     4                    (object header)                           05 00 93 19 (00000101 00000000 10010011 00011001) (429064197)
          4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
          8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
         12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         16     8   java.lang.String HelloWorld.name                           (object)
    Instance size: 24 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -------------------------
    重量锁:
    -------------------------
    com.wlf.springcloudgateway.javabean.HelloWorld object internals:
     OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
          0     4                    (object header)                           9a 7b c2 02 (10011010 01111011 11000010 00000010) (46300058)
          4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
          8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
         12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         16     8   java.lang.String HelloWorld.name                           (object)
    Instance size: 24 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -------------------------
    -------------------------
    com.wlf.springcloudgateway.javabean.HelloWorld object internals:
     OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
          0     4                    (object header)                           9a 7b c2 02 (10011010 01111011 11000010 00000010) (46300058)
          4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
          8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
         12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
         16     8   java.lang.String HelloWorld.name                           (object)
    Instance size: 24 bytes
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    
    -------------------------
    
    Process finished with exit code 0

      我们看到偏向锁在对象实例化后打开了(偏向锁状态为1,锁状态为01),第一次使用锁的时候就是用的偏向锁,持有锁的线程ID被写入对象头中,第二次该线程再次使用偏向锁,线程ID不变。随后我们使用两个其他线程来竞争该锁,偏向锁膨胀为重量锁(锁状态10),原线程ID变更为持有锁的线程指针。

  • 相关阅读:
    .hpp文件
    最小高度的BST
    检查图中的有向路径
    c++ 对象内存布局详解
    链表求差
    offer--链表反转和从尾到头打印链表
    平衡二叉树的判断
    java 抽象类和接口
    原型模式--prototype
    装饰模式decorator
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/14098987.html
Copyright © 2011-2022 走看看