美文网首页
synchronized底层实现

synchronized底层实现

作者: 叫我C30混凝土 | 来源:发表于2020-11-08 23:54 被阅读0次

    synchronized

    • java语言级的支持,1.6之后性能极大提高
    • 字节码层面的实现: monitorenter/monitorexit
    //代码
    private void increment(){ 
            synchronized(this){
                counter++;
            }
        }
    
    //字节码
    private increment()V
        TRYCATCHBLOCK L0 L1 L2 null
        TRYCATCHBLOCK L2 L3 L2 null
       L4
        LINENUMBER 22 L4
        ALOAD 0
        DUP
        ASTORE 1
        MONITORENTER //占有锁(监视器)
       L0
        LINENUMBER 23 L0
        ALOAD 0
        GETFIELD com/Coordinator$MyThread.i : Ljava/lang/Integer;
        ASTORE 2
        ALOAD 0
        ALOAD 0
        GETFIELD com/Coordinator$MyThread.i : Ljava/lang/Integer;
        INVOKEVIRTUAL java/lang/Integer.intValue ()I
        ICONST_1
        IADD
        INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
        DUP_X1
        PUTFIELD com/Coordinator$MyThread.i : Ljava/lang/Integer;
        ASTORE 3
        ALOAD 2
        POP
       L5
        LINENUMBER 24 L5
        ALOAD 1
        MONITOREXIT  // 退出锁(监视器)
       L1
        GOTO L6
       L2
       FRAME FULL [com/Coordinator$MyThread java/lang/Object] [java/lang/Throwable]
        ASTORE 4
        ALOAD 1
        MONITOREXIT
       L3
        ALOAD 4
        ATHROW
       L6
        LINENUMBER 25 L6
       FRAME CHOP 1
        RETURN
       L7
        LOCALVARIABLE this Lcom/Coordinator$MyThread; L4 L7 0
        MAXSTACK = 3
        MAXLOCALS = 5
    
    //方法2.synchronized 在方法上
    private synchronized static void doSomething(){
                i++;
            }
    
    
    • 锁住的是什么?
      - 在方法中时,锁住的是其中的对象 ;
      - 在方法上时,1. static方法锁住的是当前的class对象;2. 非static方法,锁住的是当前对象的实例;
    // 反例:
    static class MyThread extends Thread{
            private synchronized void doSomething(){
    
            }
            @Override
            public void run(){
                doSomething();
                System.out.println(123);
            }
        }
    
        public static void main(String[] args) {
            // 开启了四个线程,但synchronized 方法锁住的是每个实例自己的doSomething();所以synchronized 锁并没有用;
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
            new MyThread().start();
        }
    
    • 底层实现
      - 对象头
      - 无锁 -> 偏向锁(biased lock) -(锁膨胀)> 轻量级锁 -(锁膨胀)> 重量级锁
      无锁状态: 没有线程访问,是个游离在JVM中的对象;
      偏向锁状态: 一直以来都是同一个线程访问,该对象头会变成偏向锁,下次该线程访问,可以直接使用;此时没有锁发生,所以即使线程不再调用,标志位还会一直存在在对象头中;
      当第二个线程,尝试获取该锁,偏向锁标志位会撤销,会恢复成无锁的状态;
      轻量级锁状态: 有线程竞争的情况发生,但是不严重(同一时刻只有一个线程获取锁),假如能抢到我的话,就不需要获取monitor.
      重量级锁状态: 有多个线程在竞争锁,所以必须获取monitor;

                所以进入monitorenter时,或退出monitorexit时,不一定需要获取monitorenter或释放monitorexit;
      
          对象头定义: markOop.hpp
          锁膨胀定义: synchronizer.cpp
      
    对象头.png

    锁粗化与锁消除

    • 锁粗化: 同一个锁要连续频繁加锁解锁,粗化为更大范围的锁;
    public static void main(String[] args) {
            increment();
        }
    
        private static void increment(){
            // monitorenter
            for (int i = 0 ;i <10; i++) {
                foo();
            }
             // monitorexit
        }
    
        // foo()频繁的加锁解锁,编译器就会把他优化成更大范围的锁
        private static synchronized void foo() {
            System.out.println("");
        }
    
    • 锁消除: 不可能有人和我竞争锁,所以没必要上锁;

    相关文章

      网友评论

          本文标题:synchronized底层实现

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