前置知识:多线程同步、ReentrantLock、重入的概念
谈到Java的多线程,必然少不了传说中的AQS。那么AQS是什么?官方一点的说法来讲,AQS提供了原子值state和同步队列,是旨在实现同步相关功能的一个框架,JUC包的基础类。这样说好像有点抽象,那就从用到它的ReentrantLock入手。
画了个不太标准的类图,可以从中看出ReentrantLock里面有三个内部类,其中Sync继承自AQS,底下还有两个子类FairSync和NonfairSync,提供了lock()、isLocked()等锁相关的方法。可以说ReentrantLock锁相关的操作都是委托给内部类Sync,通过继承AQS,分别对不同类型的锁(Fair和Nonfair),提供不同的实现来对线程进行调度管理。
AQS有两个核心变量:state和同步队列(FIFO)。state表示当前对象是否被线程占有,同步队列则存储那些竞争锁失败的线程,等待唤醒,但具体优先唤醒哪个线程,那就得调的具体实现是Fair还是NonFair。
线程竞争锁的具体流程如下,有下划线的是当前步骤调用的方法:
基本上state代表锁是不是可以被获取的,ReentrantLock定的规则是为0就表示当前没线程占用可以上锁,大于0的时候表示上了多少次锁。由于ReentrantLock可重入,看见state大于0不代表要放弃,还要看当前占用的线程是哪个,是自己那还是可以重入上锁的;如果是别人就是时候放弃竞争,乖乖去同步队列排队。
以上是AQS在ReentrantLock实现的主体逻辑,主要是体验一下AQS是怎么用的,带着这些概念和框架去看具体的细枝末叶,相信会清晰很多。