- AbstractQueuedSynchronizer类的常用属性
// 头结点,可以理解为当前持有锁的线程
private transient volatile Node head;
// 阻塞的尾节点,每个新的节点进来,都插入到最后,也就形成了一个链表
private transient volatile Node tail;
// 代表当前锁的状态,0代表没有被占用,大于0代表有线程持有当前锁,这个值可以大于 1,是因为锁可以重入,每次重入都加上1
private volatile int state;
// 代表当前持有独占锁的线程,锁重入时可以用这个来判断当前线程是否已经拥有了锁
private transient Thread exclusiveOwnerThread; //继承自AbstractOwnableSynchronizer
- Node类的常用属性
static final class Node {
// 标识节点当前在共享模式下
static final Node SHARED = new Node();
// 标识节点当前在独占模式下
static final Node EXCLUSIVE = null;
//下面的几个int常量是给waitStatus用的
// 代码此线程取消了争抢这个锁
static final int CANCELLED = 1;
// 表示当前node的后继节点对应的线程需要被唤醒
static final int SIGNAL = -1;
// 线程正在唤醒等待条件
static final int CONDITION = -2;
// 线程的共享锁应该被无条件传播
static final int PROPAGATE = -3;
// 取值为上面的1、-1、-2、-3,或者0,如果这个值大于0代表此线程取消了等待
volatile int waitStatus;
// 前驱节点的引用
volatile Node prev;
// 后继节点的引用
volatile Node next;
// 线程
volatile Thread thread;
以ReentrantLock为例,ReentrantLock 在内部用了内部类 Sync 来管理锁,所以真正的获取锁和释放锁是由 Sync 的实现类来控制的。Sync 有两个实现,分别为 非公平锁NonfairSync 公平锁公平锁FairSync,我们看 FairSync 部分。
- 获取锁:通过tryAcquire尝试获取锁,如果获取失败,将当前线程包装成node,通过addWaiter方法加入阻塞队列队尾,acquireQueued执行挂起线程等操作
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// state为0表示锁没有被占用
if (c == 0) {
// 公平锁,先判断队列有没有线程在等待,没有线程等待,使用cas将state设置为1
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 没拿到锁,判断占有锁的线程是否是当前线程,如果是当前线程则可重入,
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
// state加1
setState(nextc);
return true;
}
return false;
}
acquireQueued方法处理抢占锁失败挂起线程,被唤醒后去获取锁等操作。这里的for循环只有在抢占锁成功后返回,如果线程被挂起,又被前驱结点唤醒,则变成对头结点,那么抢占锁成功,介绍循环。 final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 是头结点,而且抢占锁成功,返回
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 不是队头结点,或者抢占锁失败,shouldParkAfterFailedAcquire方法返回true,
// 执行shouldParkAfterFailedAcquire方法挂起线程,如果被前驱结点释放锁后唤醒,也是从这里开始执行。
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
当前线程没有抢到锁,是否需要挂起当前线程? private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// Node.SIGNAL表示待唤醒,前驱结点状态正常,当前线程需要挂起,直接返回
if (ws == Node.SIGNAL)
return true;
// 大于0表示取消了等待,修改前驱结点
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// state初始化为0,设置state为-1
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
挂起线程 private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
- 释放锁
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;
// c为0表示锁没有重入了,锁可以释放
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
唤醒后继结点 private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
//如果head节点当前waitStatus<0, 将其修改为0
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
// 唤醒线程
LockSupport.unpark(s.thread);
}
线程被唤醒后,从以下代码中继续往前走,回到acquireQueued方法private final boolean parkAndCheckInterrupt() {
LockSupport.park(this); // 刚刚线程被挂起在这里了
return Thread.interrupted();
}
- 参考
blog.csdn.net/zjwl199802/…