• Lock锁和AQS


    java 的锁分为两类:

    • 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见;
    • 第二类是在 jdk5 后增加的 Lock 接口以及对应的各种实现类,这属于显式的锁,就是我们能在代码层面看到锁这个对象,而这些个对象的方法实现,大都是直接依赖 CPU 指令的,无关 jvm 的实现。

    在这里插入图片描述

    synchronized 原理

    • 修饰对象 对象锁
    • 修饰类 类锁
    • 修饰方法 实例方法 对象锁 静态方法 类锁

    原理

    修饰方法 - 依靠ACC_SYNCONSIZED标志

    在执行一个方法之前,首先会识别ACC_SYNCONSIZED位,如果有,表明是一个同步方法,执行方法之前必须获取对象的Monitor,才会进去执行方法一当中内容,并且执行结束之前,其他线程无法获取当前Monitor,直到方法结束或者抛出异常。

    public class Tues {
        public static int i ;
        public synchronized static void syncTask(){
            i++;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    例子

    修饰代码快 - 依赖指令 MONITORENTER 和 MONITOREXIT 指令
    public class Test {
        public static int i ;
        public  static void syncTask(){
            synchronized (Test.class){
                i++;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    字节码: 注意其中的两个指令 MONITORENTER 和 MONITOREXIT 指令

      public static syncTask()V
        TRYCATCHBLOCK L0 L1 L2 null
        TRYCATCHBLOCK L2 L3 L2 null
       L4
        LINENUMBER 12 L4
        LDC Lcom/ll/payconter/intf/entity/Test;.class
        DUP
        ASTORE 0
        MONITORENTER
       L0
        LINENUMBER 13 L0
        GETSTATIC com/ll/payconter/intf/entity/Test.i : I
        ICONST_1
        IADD
        PUTSTATIC com/ll/payconter/intf/entity/Test.i : I
       L5
        LINENUMBER 14 L5
        ALOAD 0
        MONITOREXIT
       L1
        GOTO L6
       L2
       FRAME FULL [java/lang/Object] [java/lang/Throwable]
        ASTORE 1
        ALOAD 0
        MONITOREXIT
       L3
        ALOAD 1
        ATHROW
       L6
        LINENUMBER 15 L6
       FRAME CHOP 1
        RETURN
        MAXSTACK = 2
        MAXLOCALS = 2
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    Lock锁 原理

    Lock 完全用 Java 写成,在java这个层面是无关JVM实现的。虽然 Lock 缺少了 (通过 synchronized 块或者方法所提供的) 隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种 synchronized 关键字所不具备的同步特性。
    锁的原理,主要是依靠聚合了一个同步器(AbstractQueuedSynchronizer 缩写为 AQS)的子类来完成线程访问控制的。
    比如常见的ReentrantLock,其中内聚了Sync ,实现了AbstractQueuedSynchronizer进行线程的同步管理

     abstract static class Sync extends AbstractQueuedSynchronizer
    
    • 1

    AQS 怎么进行管理线程访问呢

    AQS原理是:如果一个共享资源是处于空闲状态,就标记当前线程为访问线程,如果当前资源处于非空闲状态,就需要一个一个线程阻塞等待以及唤醒资源分配机制,AQS通过int类型变量表示状态,使用一个FIFO的队列进行线程管理,使用CAS进行状态改变。

    什么事CAS

    什么是 CAS? CAS 即比较并替换(Compare And Swap)。CAS 操作包含三个操作数——内存位置、预期原值及新值。执行 CAS 操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。

    Lock锁就是需要AbstractQueuedSynchronizer子类进行实现

     /** Synchronizer providing all implementation mechanics */
        private final Sync sync;  手动设置公平锁或者非公平锁
    
    
    /**
         * Creates an instance of {@code ReentrantLock}.
         * This is equivalent to using {@code ReentrantLock(false)}.
         */
        public ReentrantLock() {
            sync = new NonfairSync();  默认是非公平锁
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ReentrantLock的三个实现
    参考链接

  • 相关阅读:
    SpringBoot+Vue社区团购网站(前后端分离)
    Linux 命令:head
    齐家坪水电站施工组织设计(lunwen+任务书+外文翻译+cad图纸)
    成都回顾|聚焦 · 连接 · 协同云原生数字产业生态
    Python模块ADB的, 已经 pyadb
    保姆级高通AEC9调试指南(看完可解决80%AE相关问题)
    CSS的选择器(一篇文章齐全)
    内核中自旋锁的使用
    HarmonyOS—低代码开发Demo示例
    ESP32C3 LuatOS TM1650②动态显示累加整数
  • 原文地址:https://blog.csdn.net/caijibaindashen/article/details/125899657