• 从ReentrantLock加锁解锁角度分析AQS


    本文用于记录在学习AQS时,以ReentrantLock为切入点,深入源码分析ReentrantLock的加锁和解锁过程。

    同步器AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态(通常锁或者同步组件内部会实现一个Sync类(该类是一个静态内部类),然后让Sync类去继承AQS类,通过继承AQS队列同步器并实现它的抽象方法来管理同步状态),对同步状态进行更改需要使用同步器提供的3个方法 getStatesetStatecompareAndSetState ,它们保证状态改变是安全的。

    下图是ReentrantLock中所有的内部类和方法:

    3个内部类之间的关系如下图所示:

    以ReentrantLock为例,从源码分析如何进行加锁和解锁。

    ReentrantLock lc = new ReentrantLock();
    lc.lock();
    lc.unlock();
    

    (1)ReentrantLock构造函数(为了方便分析,我们以非公平队列为例子)

    (2)lc.lock()

    ReentrantLock类中的lock()方法调用sync实例中的lock()方法,因为我们是以非公平队列为例子,所以此时的sync实例的类型为NonfairSync。即调用NonfairSync.lock()

    紧接着进入209行对应的acquire(1)方法:该方法位于AQS框架中,且被final修饰,即不能被子类重写。

    紧接着进入tryAcquire(int arg)方法

    我们发现AQS中的tryAcquire(int arg)方法中没有实现体,说明tryAcquire(int arg)方法需要AQS子类实现,根据上面的继承图可知,Sync以及NonfairSync都是AQS的子类,由下图可知,tryAcquire(int arg)方法的实现位于NonfairSync内部类中

    进入NonfairSync内部类中的ryAcquire(int arg)方法可以发现其调用了Sync静态内部类中的nonfairTryAcquire方法。

    至此成功获取了锁。

    (1) 通过ReentrantLock的加锁方法Lock进行加锁操作。
    (2) 会调用到内部类Sync的Lock方法,根据ReentrantLock初始化选择的公平锁和非公平锁,执行相关内部类的Lock方法,本质上都会执行AQS的acquire方法。
    (3) AQS的Acquire方法会执行tryAcquire方法,但是由于tryAcquire需要自定义同步器实现,因此执行了ReentrantLock中的tryAcquire方法,由于ReentrantLock是通过公平锁和非公平锁内部类实现的tryAcquire方法,因此会根据锁类型不同,执行不同的tryAcquire。
    (4) tryAcquire是获取锁逻辑,获取失败后,会执行框架AQS的后续逻辑,跟ReentrantLock自定义同步器无关。
    

    (3)lc.unlock()

    释放锁的过程和加锁过程类似,不走进源码,直接上文字版流程

    (1) 通过ReentrantLock的解锁方法Unlock进行解锁。
    (2) Unlock会调用内部类Sync的release方法,该方法继承于AQS。
    (3) release中会调用tryRelease方法,tryRelease需要自定义同步器实现,tryRelease只在ReentrantLock中的Sync实现,因此可以看出,释放锁的过程,并不区分是否为公平锁。
    (4) 释放成功后,所有处理由AQS框架完成,与自定义同步器无关。
    

    经过上述的学习,可以归纳总结出如果要自定义一个同步组件,可以按照如下步骤

    • 第一步:内部写一个Sync类继承AbstractQueuedSynchronizer接口。
    • 第二步:根据是否独占来重写队列同步器中的方法,如果需要独占则实现tryAcquire()/tryRelease()等方法,如果不需要独占,则实现tryAcquireShared(int acquires)和tryReleaseShared(int releases)等方法。
    • 第三步:初始化Sync对象,并在锁的获取/释放方法(通常为lock()以及unlock()方法)中调用AQS的acquire()/release()或者acquireShared()/releaseShared()方法。
  • 相关阅读:
    python-pycharm中使用anaconda部署python环境
    Spring Boot 整合 Redis 实现缓存操作
    Spring中的ThreadPoolTaskExecutor
    Redis-基本数据类型与内部存储结构
    Redis如何存储对象与集合示例详解
    redis存储对象
    java在注解中绑定方法参数的解决方案
    spring boot整合JMS(ActiveMQ实现)
    springboot集成activemq
    NodeJS、NPM安装配置步骤(windows版本)
  • 原文地址:https://www.cnblogs.com/XDU-Lakers/p/13934207.html
Copyright © 2020-2023  润新知