AQS源码分析NonfairSync锁源码分析staticfinalclassNonfairSyncextendsSync{privatestaticfinallongserialVersionUID=7316153563782823691L;/***执行锁定。尝试立即插入,失败时备份到normallockfinacquire。*){//跳队列获取,不排队,可以提高吞吐量if(compareAndSetState(0,1))//获取锁成功,设置ExclusiveOwnerThread=currentThreadsetExclusiveOwnerThread(Thread.currentThread());else//重要的AQS排队acquire(1);}protectedfinalbooleantryAcquire(intacquires){returnnonfairTryAcquire(acquires);}}/***以独占模式获取,忽略中断。*通过至少调用一次{@link#tryAcquire}实现,*成功返回。否则线程排队,可能*重复阻塞和解除阻塞,调用{@link*#tryAcquire}直到成功。此方法可用于*实现方法{@linkLock#lock}。**@paramarg获取参数。这个值被传送到*{@link#tryAcquire}但在其他方面没有被解释并且*可以代表你喜欢的任何东西。*/publicfinalvoidacquire(intarg){//tryAcquire(1)模板方法,再次尝试加锁,加锁成功返回True,失败返回False//addWaiter(null)CAS自旋队列的Tailofqueue//acquireQueuedCAS自旋获取lock/interrupt(park)if(!tryAcquire(arg)&&acquireQueued(addWaiter(Node.EXCLUSIVE),arg))//获取锁后检测到Interrupt=true,自中断一次自中断();}````/***执行非公平的tryLock。tryAcquire是在*子类中实现的,但是都需要对trylock方法进行非公平尝试。*/finalbooleannonfairTryAcquire(intacquires){finalThreadcurrent=Thread.当前线程();intc=getState();//再次获取锁,公平锁需要判断是否是第一个等待的Nodeif(c==0){if(compareAndSetState(0,acquires)){setExclusiveOwnerThread(current);返回真;}}//获取重新进入锁,重新进入锁直接进入state+1就好elseif(current==getExclusiveOwnerThread()){intnextc=c+acquires;if(nextc<0)//溢出thrownewError("Maximumlockcountexceeded");设置状态(下一步);返回真;}返回假;}/***为当前线程和给定模式创建并入队节点。**@parammodeNode.EXCLUSIVE为独占,Node.SHARED为共享*@return新节点*///插入队列尾部privateNodeaddWaiter(Nodemode){Nodenode=newNode(Thread.currentThread(),mode);//尝试enq的快速路径;在节点pred=tail发生故障时备份到完整enq;//快速入队优化if(pred!=null){node.prev=pred;如果(compareAndSetTail(pred,节点)){pred.next=节点;返回节点;}}//自旋入队enq(node);returnnode;}/***将节点插入队列,必要时进行初始化。见上图。*@paramnode要插入的节点*@return节点的前身*/privateNodeenq(finalNodenode){for(;;){Nodet=tail;//Head为null时,先建立Headif(t==null){//必须初始化if(compareAndSetHead(newNode()))tail=head;//把当前节插入最后}else{node.prev=t;if(compareAndSetTail(t,node)){t.next=node;返回吨;}}}}/***以独占不间断模式获取已在*队列中的线程。由条件等待方法以及获取方法使用。**@paramnode节点*@paramarg获取参数*@return{@codetrue}ifinterruptedwhilewaiting*///CAS自旋要么成功,要么中止finalbooleanacquireQueued(finalNodenode,intarg){//锁定失败标志booleanfailed=true;try{//加锁过程是否已经中断booleaninterrupted=false;for(;;){//node.predecessorfinalNodep=node.predecessor();//判断是否是第一个排队等待的线程//head一般是正在处理的线程节点,队列中第二个节点是第一个排队等待的线程节点if(p==head&&tryAcquire(arg)){setHead(节点);p.next=null;//帮助GCfailed=false;返回中断;}//没有加锁成功,判断是否中断//之前的Node.waitStatus==-1(之前的线程正在等待锁资源)if(shouldParkAfterFailedAcquire(p,node)&&parkAndCheckInterrupt())interrupted=true;}}finally{if(failed)cancelAcquire(node);}}/***检查并更新获取失败的节点的状态。*如果线程应该阻塞,则返回true。这是所有交流中的主要信号*控制需要循环。要求pred==node.prev。**@parampred节点的前驱持有状态*@paramnode节点*@return{@codetrue}ifthreadshouldblock*///判断节点是否通过pred.waitStatus是否需要暂停privatestaticbooleanshouldParkAfterFailedAcquire(Nodepred,节点node){intws=pred.waitStatus;//前驱节点(前一个线程)还没有获取到锁,挂起//pred.waitStatus==Node.SIGNAL,前驱节点正在等待资源if(ws==Node.SIGNAL)/**本节点已经设置状态要求释放*发出信号,因此它可以安全地停放。*/返回真;if(ws>0){/**前任被取消。跳过前辈,*表示重试。*///删除节点之前的无效节点do{node.prev=pred=pred.prev;}while(pred.waitStatus>0);预测。下一个=节点;}else{/**waitStatus必须为0或PROPAGATE。表明我们*需要信号,但不要停车然而。来电者需要*重试以确保它在停车前无法获取。*/compareAndSetWaitStatus(pred,ws,Node.SIGNAL);}returnfalse;}/***停放然后检查是否中断的便捷方法**@return{@codetrue}如果中断*/privatefinalbooleanparkAndCheckInterrupt(){//LockSupport.park中断LockSupport.park(this);//返回是否被中断标志returnThread.interrupted();}
