Condition
condition和synchronized的区别:
synchronized是一对一的关系,使用synchronized其实是在jvm层面创建了一个monitor对象,然后再去调用monitor对象的wait()方法和notify()方法
condition是一对多的关系,一个lock对象可以创建多个condition对象,从而去调用多个await()方法和signal()方法
await()方法
public final void await() throws InterruptedException {
//如果当前线程是中断状态,抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
//调用了await方法,说明此节点需要进入condition条件队列
//调用addConditionWaiter来入队
Node node = addConditionWaiter();//此时node在条件队列是尾节点
//释放锁
int savedState = fullyRelease(node);
//0 在condition队列挂起期间未接收过过中断信号
//-1 在condition队列挂起期间接收到中断信号了
//1 在condition队列挂起期间为未接收到中断信号,但是迁移到“阻塞队列”之后 接收过中断信号。
int interruptMode = 0;
//判断当前节点是否被移动到了阻塞队列中
//true的话执行唤醒逻辑
//false执行挂起逻辑
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);
}
addConditionWaiter()
private Node addConditionWaiter() {
//拿到全局变量尾节点,保存到t中
Node t = lastWaiter;
//t != null 说明条件队列是存在的 并且状态不为condition 说明当前节点发生了中断
//执行清除条件队列中取消状态的节点逻辑
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
//更新尾节点引用,上面的清除方法可能会改变尾节点
t = lastWaiter;
}
//如果当前节点不是中断节点,则将状态设置为condition,并且执行入队操作,并返回尾节点
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
unlinkCancelledWaiters()
//清除中断节点逻辑
//如果判断条件队列尾节点状态不为condition,才会进入到这个方法
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
//表示当前链表中,上一个状态为condition的节点
Node trail = null;
//循环迭代将所有非condition状态节点出队
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
fullyRelease()
//释放锁逻辑
//成功返回锁数量,失败抛出异常,并且修改当前入队节点状态为cancelled
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
isOnSyncQueue()
//状态为condition,返回false
//状态为0,且prev不为null && next不为null 返回true
//状态为0,prev为null,返回false
//状态为0,prev不为null,但是next为null,说明是尾节点,去遍历,遍历成功返回true
//状态为cancell,prev一定是null,返回false
final boolean isOnSyncQueue(Node node) {
//如果当前节点状态为condition,说明一定在条件队列中
//如果当前节点状态不为condition,要么是0 要是是 -1
//所有去判断前置节点是否为空,为空说明当前节点只是被修改了状态,但是还未完全被迁移到阻塞队列中
//取消状态节点肯定不会被signal方法迁移到阻塞队列中
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
//只有状态不为condition且前置节点不为空的节点才会到这里判断
if (node.next != null) // If has successor, it must be on queue
return true;
return findNodeFromTail(node);
}
signal()
public final void signal() {
//非独占锁模式,抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//拿到条件队列中的第一个节点,然后去调用doSignal方法
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
doSignal()
private void doSignal(Node first) {
do {//移动节点
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
//出队,所有将下一个节点的指针指向空
first.nextWaiter = null;
//while里面做迁移到阻塞队列的工作
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
transferForSignal()
final boolean transferForSignal(Node node) {
//如果节点状态时condition,则会修改为0
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
//加入阻塞队列
Node p = enq(node);
//拿到当前节点前置节点的状态
int ws = p.waitStatus;
//如果前置节点状态为0或者为-1,就修改为signal
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}