AQS:AbstractQueuedSynchronizer(抽象队列同步器),AQS提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,了解了AQS基本就了解了java同步机制。
AQS源码解读
1 AQS的设计模式:模板方法模式。
2 AQS中方法:
模板(框架)方法:
-
独占式获取同步状态方法:
accquire(忽略中断)
acquirelnterruptibly(能响应中断):使等待进入acquire()方法的线程,不允许被中断
tryAcquireNanos -
共享式获取同步状态方法:
acquireShared
acquireSharedInterruptibly
tryAcquireSharedNanos -
独占式释放锁。
release
-
共享式释放锁。
releaseShared.
需要子类重写的流程方法: -
独占式获取
tryAcquire -
独占式释放
tryRelease -
共享式获取
tryAcquireShared -
共享式释放
tryReleaseShared -
这个同步器是否处于独占模式。
isHeldExclusively
同步状态:state
这三种方法均是原子操作,其中compareAndSetState的实现依赖于Unsafe的compareAndSwapInt()方法
- getSate:获取当前的同步状态。
- setState:设置当前同步状态。
- compareAndSetState:使用CAS设置状态,保证状态设置的原子性
AQS中的数据结构-节点和同步队列
-
addWaiter(Node):
将当前线程节点加入到队列尾部 -
enq(Node):
将当前节点插入等待队列(自旋) -
acquireQueued(Node, int):
acquireQueued()用于队列中的线程自旋地以独占且不可中断的方式获取同步状态(acquire),直到拿到锁之后再返回。该方法的实现分成两部分:如果当前节点已经成为头结点,尝试获取锁(tryAcquire)成功,然后返回;否则检查当前节点是否应该被park,然后将该线程park并且检查当前线程是否被可以被中断。
AQS中的内部类Node: -
CANCELLED:线程等待超时或者被中断了,需要从队列中移走。
-
SIGNAL:后续的节点等待状态,当前节点,通知后面的节点去运行。
-
CONDITION:当前节点处于等待队列。
-
PROPAGATE:共享表示状态要往后面的节点传播
-
Thread:获取锁失败的线程
**AQS中流程:**当线程获取锁失败时,会被打包成Node进入同步队列中,同步队列就负责维护等待锁的线程节点。
节点在队列中的进出:
独占式同步状态的获取和释放: