ThreadAThreadBThreadCThreadD的使用示例——(专业的队列跳线)Locklock=newReentrantLock();lock.lock();//ThreadA在这里阻塞lock.newCondition().await();//做业务..lock.unlock();//————畅快的分界线————lock.lock();//ThreadB进入这里,触发signallock.newCondition().signal();lock.unlock();1.图await条件:await()在lock()和unlock()之间执行——执行await的方法必须持有锁(所有者记录的线程)步骤A:await执行时会做三件事:1.清除state和owner2.唤醒工作队列的head.next3.加入并阻塞在等待队列中步骤B:绑定到head.next节点的线程(图中的ThreadB)被唤醒,试图抢占锁。抢占成功从工作队列中移除(当然ThreadB执行await时,也会重复步骤A)2.图形signalSignal只做一件事,释放并迁移等待队列的头节点到工作的尾部queue(尾部插入,图中绿色Line)ThreadA的真正释放要等待unlock()方法。下面用代码来详细解释上面两张图。1.结构描述Condition结构publicclassConditionObjectimplementsCondition,java.io.Serializable{/**条件队列的第一个节点。*/privatetransientNodefirstWaiter;/**条件队列的最后一个节点。*/privatetransientNodelastWaiter;NodestructureclassNode{/**exclusive*/staticfinalNodeEXCLUSIVE=null;/**waitStatus值指示后继线程需要unparking*/staticfinalintSIGNAL=-1;/**waitStatus值指示线程正在等待条件*/staticfinalintCONDITION=-2;/**持有线程*/volatileThreadthread;/**等待队列相关*/volatileintwaitStatus;节点nextWaiter;/**工作队列相关*/volatileNodeprev;接下来是可变节点;2.awaitpublicfinalvoidawait()throwsInterruptedException{if(Thread.interrupted())thrownewInterruptedException();//==1.创建条件等待队列(一个新的等待队列),node为尾节点Nodenode=addConditionWaiter();//==2.清除状态state和unblock状态->其他线程此时可以抢占锁intsavedState=fullyRelease(node);中断模式=0;//==3.1,不在工作队列中//这里限制:只有工作队列中的节点才能跳出循环,进入3.2逻辑while(!isOnSyncQueue(node)){LockSupport.park(this);如果((interruptMode=checkInterruptWhileWaiting(节点))!=0)中断;}//==3.2。在工作队列中,尝试排队获取锁(如果没有获取到锁,工作会被阻塞队列)if(acquireQueued(node,savedState)&&interruptMode!=THROW_IE)interruptMode=REINTERRUPT;if(node.nextWaiter!=null)//如果取消则清理unlinkCancelledWaiters();if(interruptMode!=0)reportInterruptAfterWait(interruptMode);}1.创建等待队列//移除处于“已取消”状态的节点if(t!=null&&t.waitStatus!=Node.CONDITION){unlinkCancelledWaiters();t=最后一个服务员;}//创建node节点,waitStatus标记为condition->`-2`Nodenode=newNode(Thread.currentThread(),Node.CONDITION);如果(t==null)firstWaiter=节点;否则t.nextWaiter=节点;lastWaiter=节点;returnnode;}2.释放锁java.util.concurrent.locks.AbstractQueuedSynchronizer#fullyReleasefinalintfullyRelease(Nodenode){booleanfailed=true;尝试{intsavedState=getState();//恢复状态,清除exclusiveOwnerThread;释放工作队列中的第一个阻塞线程(ThreadB)if(release(savedState)){failed=false;返回保存状态;}else{抛出新的IllegalMonitorStateException();}}finally{if(failed)node.waitStatus=Node.CANCELLED;}}3.1是否在工作队列中finalbooleanisOnSyncQueue(Nodenode){//--等待队列节点,或者之前没有节点,一定不在工作队列中,返回falseif(node.waitStatus==Node.CONDITION||node.prev==null)returnfalse;//--在队列中,返回trueif(node.next!=null)//如果有后继者,它必须在队列中returntrue;//--从工作队列的尾部查找returnfindNodeFromTail(node);}3.2队列获取(在ReentrantLock中分析过,直接粘贴)java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueuedfinalbooleanacquireQueued(finalNodenode,intarg){布尔失败=true;尝试{布尔中断=false;//循环for(;;){finalNodep=node.predecessor();//###前面的节点是头节点,有机会尝试获取它//(结合下一个if判断,会自旋两次,也就是说有两次尝试获取它)if(p==head&&tryAcquire(arg)){setHead(node);p.next=null;//帮助GCfailed=false;返回中断;}//###第一次设置waitstatus为signal返回false//###第二次判断waitstatus==signal返回trueif(shouldParkAfterFailedAcquire(p,node)//===线程阻塞(当future醒了,从这里继续执行)&&parkAndCheckInterrupt())interrupted=true;}}finally{if(failed)cancelAcquire(node);}}###privatestaticbooleanshouldParkAfterFailedAcquire(Nodepred,Nodenode){intws=pred.waitStatus;//--第二次调用if(ws==Node.SIGNAL)returntrue;如果(ws>0){做{node.prev=pred=pred.prev;}while(pred.waitStatus>0);pred.next=n颂;}//--首先调用else{compareAndSetWaitStatus(pred,ws,Node.SIGNAL);}returnfalse;}===privatefinalbooleanparkAndCheckInterrupt(){LockSupport.park(this);//当前线程是否被中断returnThread.interrupted();}3.signaljava.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#signalpublicfinalvoidsignal(){//exclusiveOwnerThread持有线程判断if(!isHeldExclusively())抛出新的IllegalMonitorStateException();Nodefirst=firstWaiter;//唤醒的是等待队列的头节点if(first!=null)//==队列节点转移(等待队列->工作队列)doSignal(first);}java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#doSignalprivatevoiddoSignal(Nodefirst){do{//--释放等待队列的头节点if((firstWaiter=first.nextWaiter)==null)lastWaiter=null;first.nextWaiter=null;}while(//--节点转移!transferForSignal(first)&&(first=firstWaiter)!=null);}finalbooleantransferForSignal(Nodenode){/**如果不能改变waitStatus,节点已经被取消。*/if(!compareAndSetWaitStatus(node,Node.CONDITION,0))返回false;//尾插工作队Nodep=enq(node);intws=p.waitStatus;如果(ws>0||!compareAndSetWaitStatus(p,ws,Node.SIGNAL))LockSupport.unpark(node.thread);返回真;}
