1 take堵塞操作 (区分 poll() 非堵塞以及 中间状态 poll(long timeout, TimeUnit unit))
// 有异常
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
2 源码分析
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
// 有锁进入等待队列
// 有锁进入等待队列
// 有锁进入等待队列
// 有锁进入等待队列
// 有锁进入等待队列
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter(); // Adds a new waiter to wait queue.
int savedState = fullyRelease(node); // 消费者释放资源,从clh中移除,唤醒后续节点
int interruptMode = 0;
while (!isOnSyncQueue(node)) { // 不在同步clh 队列,在等待队列
LockSupport.park(this); // park
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);
}
/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
* @param node the condition node for this wait
* @return previous sync state
*/
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState(); // 获取当前状态 state
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
public final boolean release(int arg) {
if (tryRelease(arg)) { // 释放arg个资源
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h); // 源码 唤醒后续节点
return true;
}
return false;
}
// 释放arg个资源
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { // 独享锁reset
free = true;
setExclusiveOwnerThread(null); // 清空占有者
}
setState(c); // 设置state
return free;
}
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
// 源码 唤醒后续节点
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
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); // 唤醒的节点线程,race state
}
// 释放资源lock ,即从clh队列移除头节点,分析完毕
// 无锁状态等待唤醒--堵塞业务逻辑
// 无锁状态等待唤醒--堵塞业务逻辑
// 无锁状态等待唤醒--堵塞业务逻辑
// 无锁状态等待唤醒--堵塞业务逻辑
// 结下来是park前执行isOnSyncQueue(node)是无锁状态只做查询操作
// LockSupport.park(this);
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node); // 已经彻底释放了锁,下面操作是在无锁状态下执行
int interruptMode = 0;
// 有可能不需要park就能立即被唤醒运行
// 可能正在被其他生产者转移到clh队列,node.prev = t;-->compareAndSetTail(t, node)
while (!isOnSyncQueue(node)) { // 检测节点是否被移动到了 clh队列上,如果没有,则堵塞park
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);
}
/**
* Returns true if a node, always one that was initially placed on
* a condition queue, is now waiting to reacquire on sync queue.
* @param node the node
* @return true if is reacquiring
*/
//
final boolean isOnSyncQueue(Node node) {
// node.waitStatus == Node.CONDITION一定是还在等待队列 (volatile int waitStatus;)
// transferForSignal 先执行更改状态,再去入队
// node.prev == null 可能是入队中(并发),入队成功就能等待前序节点来唤醒了
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
// node.next最后set 确保一定入队clh
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
return findNodeFromTail(node);
}
/**
* Returns true if node is on sync queue by searching backwards from tail.
* Called only when needed by isOnSyncQueue.
* @return true if present
*/
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
// 被激活再次获取锁--执行业务逻辑
// 被激活再次获取锁--执行业务逻辑
// 被激活再次获取锁--执行业务逻辑
// 被激活再次获取锁--执行业务逻辑
// 被激活再次获取锁--执行业务逻辑
// 被激活再次获取锁--执行业务逻辑
// 结下来是clh队列激活--->当前线程 从park中醒来
// 执行 acquireQueued race state
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node); // 已经彻底释放了锁,下面操作是在无锁状态下执行
int interruptMode = 0;
// 有可能不需要park就能立即被唤醒运行
// 可能正在被其他生产者转移到clh队列,node.prev = t;-->compareAndSetTail(t, node)
while (!isOnSyncQueue(node)) { // 检测节点是否被移动到了 clh队列上,如果没有,则堵塞park
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);
}
// Acquires in exclusive mode, ignoring interrupts. 和acquire中的acquireQueued一样,race state
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
* 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();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
3 小结
1 线程take搭配lock,
2 后去不到时,执行await 其中经历了如下:
- 阶段1: 锁环境下---加入条件队列----释放锁---LockSupport.park // 放弃竞争
- 阶段2: 被生产者从条件移除,并加入到clh队列-----race时被唤醒-----退出LockSupport.park // 只是入队
- 阶段3: 再次race获取锁(有可能再次被park,因为在非公平锁可能并发竞争)--竞争到---->继续执行业务逻辑或异常处理 // 去竞争