acquire()方法
调用tryAcquire()方法判断同步状态是否满足,如果不满足则将线程封装成节点,加入到同步队列。加入到队列后的线程会反复阻塞,每次被唤醒后都再次调用tryAcquire()方法判断同步状态是否满足,如果仍然不满足,继续阻塞等待,直至同步状态满足为止。由于该方法忽略中断,所以在被唤醒后不会判断线程是否被中断。相对地,acquireInterruptibly()方法在被唤醒后会判断线程是否被中断,所以他退出阻塞的条件有2个:1、线程被中断;2、同步状态满足。
addWaitor()方法:将将线程封装成节点,加入到同步队列。
acquireQueued()方法:调用LockSupport.park()方法进行阻塞,在每次被唤醒后都再次调用tryAcquire()方法判断同步状态是否满足。
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
acquireQueued()方法
调用LockSupport.park()方法进行阻塞,在每次被唤醒后都再次调用tryAcquire()方法判断同步状态是否满足。
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
//同步队列在初始化时,tail节点等于head节点,此后每加入一个新节点,则tail节点等于该新节点,详见addWaitor()方法
//如果它的前继节点等于头结点,并且同步状态满足,则将当前节点设置为头结点
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//在当前节点获取锁失败时判断是否应该使线程阻塞等待
if (shouldParkAfterFailedAcquire(p, node) &&
//如果应该阻塞,调用LockSupport.park()方法进行阻塞
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire()方法
在当前节点调用tryAcquire()方法失败时,判断是否应该使线程阻塞等待。
线程应该阻塞等待的条件为:前继节点的waitStatus为SIGNAL。
针对前继节点的waitStatus,分为以下三种情形 :
- 如果前继节点的waitStatus为SIGNAL,表示该节点请求在前继节点释放锁时通知它,所以应该阻塞等待;
- 如果前继节点的waitStatus大于0,说明该节点的前继节点是cancelled状态,后续遍历找到状态不为cancelled状态的前继节点;
- 如果前继节点的waitStatus等于0或者PROPAGATE,表示该节点请求在前继节点释放锁时通知它,但还不能调用park()方法进行阻塞,通过cas设置前继节点的waitStatus为SIGNAL;
/**
* Checks and updates status for a node that failed to acquire.
* Returns true if thread should block. This is the main signal
* control in all acquire loops. Requires that pred == node.prev.
*
* @param pred node's predecessor holding status
* @param node the node
* @return {@code true} if thread should block
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
//如果前继节点的waitStatus为SIGNAL,表示该节点请求在前继节点释放锁时通知它,所以应该阻塞等待
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
//如果前继节点的waitStatus大于0,说明该节点的前继节点是cancelled状态,后续遍历找到状态不为cancelled状态的前继节点
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
//如果前继节点的waitStatus等于0或者PROPAGATE,表示该节点请求在前继节点释放锁时通知它,但还不能调用park()方法进行阻塞,通过cas设置前继节点的waitStatus为SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}