|
| 1 | +## AQS: AbstractQueuedSynchronizer/AbstractOwnableSynchronizer/AbstractQueuedLongSynchronizer |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +1. 简介 |
| 6 | + |
| 7 | + - Abstract: 符合模板模式, 核心父类被集成, 形成钩子调用 |
| 8 | + - Queued: 对抢不到锁的线程的管理 |
| 9 | + - Synchronizer: 尝试去抢占锁, 管理好在排队的暂时没有抢到锁的线程 |
| 10 | + - 用来构建锁[ReentrantLock]和其他同步器组件[CountDownLatch/CyclicBarrier/Semapthore]的基石[framework] |
| 11 | + - 通过内置的 queue[CLH] 来完成线程的排队管理工作, 并通过一个 int 型变量表示锁的持有[volatile state] |
| 12 | + |
| 13 | +2. 简介 2 |
| 14 | + |
| 15 | + - 已获取锁的线程执行逻辑, 其他抢占锁失败会被阻塞但依旧有抢占锁的机会, 因此阻塞的线程需要使用 queue[CLH 的变种实现] 进行排队管理 |
| 16 | + - 如果共享资源被占用了, 就需要一定的知识唤醒机制来保证锁的分配 |
| 17 | + - 通过自旋, CAS, LockSupport 等方式维护 state 的变量状态 |
| 18 | + |
| 19 | +3. 综述 |
| 20 | + |
| 21 | + - AQS 使用一个 volatile 的 int 类型的的成员变量表示同步状态, |
| 22 | + - 通过内置的 FIFO 队列完成资源的排队工作, 将每一条要去抢占的资源的线程封装成一个 Node 节点来实现锁的分配, 通过 CAS 完成对 state 的修改 |
| 23 | + |
| 24 | +4. line - framework |
| 25 | + |
| 26 | +  |
| 27 | + |
| 28 | +  |
| 29 | + |
| 30 | + - state: 0 表示未被占用, 1 表示已被占用, > 1 表示重入锁 |
| 31 | + - 内部是 CLH 的双向队列 Node[内部是有 Thread 线程(表示占有锁的线程)]: `自旋` |
| 32 | + |
| 33 | + - code |
| 34 | + |
| 35 | + ```java |
| 36 | + public abstract class AbstractQueuedSynchronizer { |
| 37 | + private transient volatile Node head; |
| 38 | + private transient volatile Node tail; |
| 39 | + // 表示锁是否空闲 |
| 40 | + private volatile int state; |
| 41 | + |
| 42 | + static final class Node { |
| 43 | + volatile Node next; |
| 44 | + volatile Node prev; |
| 45 | + |
| 46 | + // 以共享方式等待锁 |
| 47 | + static final Node SHARED = new Node(); |
| 48 | + // 以排他方式等待锁 |
| 49 | + static final Node EXCLUSIVE = null; |
| 50 | + |
| 51 | + // 每一个等待线程的状态 |
| 52 | + // 1. CANCELLED = 1: 线程获取锁的请求已经取消 |
| 53 | + // 2. SIGNAL = -1: 线程程序已经准备好, 就等资源释放了 |
| 54 | + // 3. CONDITION = -2: 在队列中, 等待被唤醒 |
| 55 | + // 4. PROPAGATE = -3: 当线程处于 SHARED 模式下才会使用 |
| 56 | + volatile int waitStatus = 0; |
| 57 | + |
| 58 | + // 当前占用锁的线程 |
| 59 | + volatile Thread thread; |
| 60 | + } |
| 61 | + } |
| 62 | + ``` |
| 63 | + |
| 64 | +5. ReentrantLock |
| 65 | + |
| 66 | + - Lock 接口的实现类一般都是通过聚合一个 `队列同步器` 的子类完成访问控制的 |
| 67 | + - code layout |
| 68 | + |
| 69 | + ```java |
| 70 | + public class ReentrantLock implements Lock, java.io.Serializable { |
| 71 | + |
| 72 | + public ReentrantLock(boolean fair) { |
| 73 | + sync = fair ? new FairSync() : new NonfairSync(); |
| 74 | + } |
| 75 | + |
| 76 | + private final Sync sync; |
| 77 | + abstract static class Sync extends AbstractQueuedSynchronizer { |
| 78 | + } |
| 79 | + |
| 80 | + static final class FairSync extends Sync { |
| 81 | + final void lock() {} |
| 82 | + protected final boolean tryAcquire(int acquires) {} |
| 83 | + } |
| 84 | + |
| 85 | + static final class NonfairSync extends Sync { |
| 86 | + final void lock(){} |
| 87 | + protected final boolean tryAcquire(int acquires) {} |
| 88 | + } |
| 89 | + } |
| 90 | + ``` |
0 commit comments