• Java 隐式锁


    Java 中关键字 synchronized 表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程。

    作用:

    • 确保线程互斥地访问同步代码
    • 保证共享变量的修改能够及时可见
    • 有效解决重排序问题

    用法:

    • 修饰普通方法
    • 修饰静态方法
    • 指定对象,修饰代码块

    特点:

    • 阻塞未获取到锁、竞争同一个对象锁的线程
    • 获取锁无法设置超时
    • 无法实现公平锁
    • 控制等待和唤醒需要结合加锁对象的 wait() 和 notify()、notifyAll()
    • 锁的功能是 JVM 层面实现的
    • 在加锁代码块执行完或者出现异常,自动释放锁

    原理:

    • 同步代码块是通过 monitorenter 和 monitorexit 指令获取线程的执行权
    • 同步方法通过加 ACC_SYNCHRONIZED 标识实现线程的执行权的控制

    测试代码:

    public class TestSynchronized {
        
        public void sync() {
            synchronized (this) {
                System.out.println("sync");
            }
        }
        
        public synchronized void syncdo() {
            System.out.println("syncdo");
        }
        
        public static synchronized void staticSyncdo() {
            System.out.println("staticSyncdo");
        }
    }

    通过JDK 反汇编指令 javap -c -v TestSynchronized

    javap -c -v TestSynchronized
     
      Last modified 2019-5-27; size 719 bytes
      MD5 checksum e5058a43e76fe1cff6748d4eb1565658
      Compiled from "TestSynchronized.java"
    public class constxiong.interview.TestSynchronized
      minor version: 0
      major version: 49
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Class              #2             // constxiong/interview/TestSynchronized
       #2 = Utf8               constxiong/interview/TestSynchronized
       #3 = Class              #4             // java/lang/Object
       #4 = Utf8               java/lang/Object
       #5 = Utf8               <init>
       #6 = Utf8               ()V
       #7 = Utf8               Code
       #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
       #9 = NameAndType        #5:#6          // "<init>":()V
      #10 = Utf8               LineNumberTable
      #11 = Utf8               LocalVariableTable
      #12 = Utf8               this
      #13 = Utf8               Lconstxiong/interview/TestSynchronized;
      #14 = Utf8               sync
      #15 = Fieldref           #16.#18        // java/lang/System.out:Ljava/io/PrintStream;
      #16 = Class              #17            // java/lang/System
      #17 = Utf8               java/lang/System
      #18 = NameAndType        #19:#20        // out:Ljava/io/PrintStream;
      #19 = Utf8               out
      #20 = Utf8               Ljava/io/PrintStream;
      #21 = String             #14            // sync
      #22 = Methodref          #23.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
      #23 = Class              #24            // java/io/PrintStream
      #24 = Utf8               java/io/PrintStream
      #25 = NameAndType        #26:#27        // println:(Ljava/lang/String;)V
      #26 = Utf8               println
      #27 = Utf8               (Ljava/lang/String;)V
      #28 = Utf8               syncdo
      #29 = String             #28            // syncdo
      #30 = Utf8               staticSyncdo
      #31 = String             #30            // staticSyncdo
      #32 = Utf8               SourceFile
      #33 = Utf8               TestSynchronized.java
    {
      public constxiong.interview.TestSynchronized();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #8                  // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 3: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lconstxiong/interview/TestSynchronized;
     
      public void sync();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=1
             0: aload_0
             1: dup
             2: astore_1
             3: monitorenter
             4: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
             7: ldc           #21                 // String sync
             9: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            12: aload_1
            13: monitorexit
            14: goto          20
            17: aload_1
            18: monitorexit
            19: athrow
            20: return
          Exception table:
             from    to  target type
                 4    14    17   any
                17    19    17   any
          LineNumberTable:
            line 6: 0
            line 7: 4
            line 6: 12
            line 9: 20
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0      21     0  this   Lconstxiong/interview/TestSynchronized;
     
      public synchronized void syncdo();
        descriptor: ()V
        flags: ACC_PUBLIC, ACC_SYNCHRONIZED
        Code:
          stack=2, locals=1, args_size=1
             0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
             3: ldc           #29                 // String syncdo
             5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
             8: return
          LineNumberTable:
            line 12: 0
            line 13: 8
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       9     0  this   Lconstxiong/interview/TestSynchronized;
     
      public static synchronized void staticSyncdo();
        descriptor: ()V
        flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
        Code:
          stack=2, locals=0, args_size=0
             0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
             3: ldc           #31                 // String staticSyncdo
             5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
             8: return
          LineNumberTable:
            line 16: 0
            line 17: 8
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
    }
    SourceFile: "TestSynchronized.java"



      

     来一道刷了进BAT的面试题?

  • 相关阅读:
    计算机中最重要的两个硬件是什么它们如何相互作用。
    音乐光盘
    下列各项包含多少位?
    下列包含多少字节?
    自测题‘
    自测题.
    python 并发编程多线程之进程池/线程池
    python 并发编程之多线程
    基于解决高并发生的产者消费者模型
    守护进程、互斥锁、进程间通信(IPC机制)
  • 原文地址:https://www.cnblogs.com/ConstXiong/p/11687745.html
Copyright © 2020-2023  润新知