数据结构
AQS涉及数据结构
static final class Node {
// 共享节点-- 读写锁中读锁
static final Node SHARED = new Node();
// 独占节点
static final Node EXCLUSIVE = null;
// 队列中节点的状态 0/SIGNAL 存在AQS队列;CONDITION 存在Condition 队列
volatile int waitStatus;
// 双链表前驱
volatile Node prev;
// 双链表后继
volatile Node next;
// 单链表下一节点
Node nextWaiter;
...
}
public abstract class AbstractQueuedSynchronizer{
// AQS 队列头节点
private transient volatile Node head;
// AQS 队列尾节点
private transient volatile Node tail;
// 同步状态
// ReentrantLock 0- 无锁,1-有锁,>1 重入锁
private volatile int state;
...
}
public class ConditionObject implements Condition, java.io.Serializable {
// condition 队列头节点
private transient Node firstWaiter;
// condition 队列未节点
private transient Node lastWaiter;
}
注意
- AQS 队列是一个双向链表
- Condition队列是一个单向链表
- t.waitStatus = Node.CONDITION 标识节点在Condition队列
- t.waitStatus=0/Node.SIGNAL 标识节点在AQS队列
ReentrantLock 源码分析
锁的实现(设计思维--互斥锁)
- 锁的互斥特性 -> 共享资源 -> 标记位(0--无锁,1--有锁)
- 没有抢到锁的线程?->释放CPU 资源(等待 -> 唤醒)
- 等待线程如何存储? -> 数据结构去存储一些等待中的线程,FIFO(等待线程)
- 公平非公平(能否插队)
- 重入的特性(是否是一个人?ThreadId)
技术方案
- volatile state 0-无锁,1 代表持有锁,>1 代表重入
- wait/notify |Condition 需要唤醒指定线程 Lock support.park();-> unpark()
- 双向链表实现 FIFO
- 逻辑层实现公平和非公平锁
- 在某一个地方存储当前获得锁的线程的Id,判断是否是持有锁的线程。
lock()
/**
* The current owner of exclusive mode synchronization.
*/
private transient Thread exclusiveOwnerThread;
/**
* The synchronization state.
*/
private volatile int state;
final void lock() {
// 比较是否无锁,乐观锁比较
if (compareAndSetState(0, 1))
// 无锁设置当前线程拥有锁
setExclusiveOwnerThread(Thread.currentThread());
else
// 再次抢占锁
acquire(1);
}
publi c final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
- !tryAcquire(arg) 抢占锁
- acquireQueued 尝试抢占锁,不成功阻塞等待
- addWaiter 初始化,在队尾添加节点
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 无锁,抢占锁
if (compareAndSetState(0, acquires)) {
// 无锁设置当前线程拥有锁
setExclusiveOwnerThread(current);
return true;
}
}
// 判断是否重入锁
else if (current == getExclusiveOwnerThread()) {
// 重入锁,增加state值
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);// 已经是独占状态,不需要通过cas
return true;
}
return false;
}
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
// cas 设置链表tail为插入的node 节点
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
// cas 初始化链表,添加一个空的头节点
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
// cas 设置链表tail为插入的node 节点
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 获取node的前继节点
final Node p = node.predecessor();
// 是头节点的话,也就是node为第二个节点,尝试获取锁
if (p == head && tryAcquire(arg)) {
// 获取锁成功,则更新头节点为当前节点,消除冗余节点
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// node不是头节点或者获取锁失败,执行判断是否需要阻塞等待
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
unlock()
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
// 唤醒头节点
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
// 获取状态值
int c = getState() - releases;
// 判断当前线程是否持有锁
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 判断是否为重入锁
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 设置重入次数
setState(c);
return free;
}
ReentrantReadWriteLock
CountDownLatch
注意
- AQS 中的 state 维护计数值
- 当计数值==0,唤醒阻塞线程
- latch.countDown()计算值减一
- latch.await() 等待计数器为0时唤醒
Semaphore
注意
- AQS 中的 state 维护令牌数
- semaphore.acquire()申请信号量
- semaphore.release()释放信号量
Condition
条件队列,线程被await操作挂起后放入条件队列,等待signal操作唤醒进入AQS队列
阻塞线程
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 将当前线程构造成条件节点加入condition的条件队列尾部,node即为构造的节点
Node node = addConditionWaiter();
// 完全释放锁,wait是要释放当前持有锁的,返回释放锁之前状态
int savedState = fullyRelease(node);
int interruptMode = 0;
// isOnSyncQueue为true代表node已被转移到AQS队列;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 获取锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
唤醒线程
public final void signal() {
// 是否占有锁
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
// 拿到Condition头节点
Node first = firstWaiter;
if (first != null)
// 唤醒头节点
doSignal(first);
}
private void doSignal(Node first) {
do {
// 判断Condition队列头节点后继节点是否为空
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 把node加入AQS队列
Node p = enq(node);
int ws = p.waitStatus;
// ws>0 是cancel状态,抛出异常后状态会变为cancel
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
// 节点拿到独占锁,直接唤醒
LockSupport.unpark(node.thread);
return true;
}