详解tryAcquire()、addWaiter()、acquireQueued()
本文实例为大家分享了tryAcquire()、addWaiter()、acquireQueued()的用法,供大家参考,具体内容如下
tryAcquire()
finalbooleannonfairTryAcquire(intacquires){ finalThreadcurrent=Thread.currentThread(); intc=getState(); if(c==0){ if(compareAndSetState(0,acquires)){ setExclusiveOwnerThread(current); returntrue; } } elseif(current==getExclusiveOwnerThread()){ intnextc=c+acquires; if(nextc<0)//overflow thrownewError("Maximumlockcountexceeded"); setState(nextc); returntrue; } returnfalse; }
先判断state是否为0,如果为0就执行上面提到的lock方法的前半部分,通过CAS操作将state的值从0变为1,否则判断当前线程是否为exclusiveOwnerThread,然后把state++,也就是重入锁的体现,我们注意前半部分是通过CAS来保证同步,后半部分并没有同步的体现,原因是:后半部分是线程重入,再次获得锁时才触发的操作,此时当前线程拥有锁,所以对ReentrantLock的属性操作是无需加锁的。如果tryAcquire()获取失败,则要执行addWaiter()向等待队列中添加一个独占模式的节点。
addWaiter()
/** *Createsandenqueuesnodeforcurrentthreadandgivenmode. * *@parammodeNode.EXCLUSIVEforexclusive,Node.SHAREDforshared *@returnthenewnode */ privateNodeaddWaiter(Nodemode){ Nodenode=newNode(Thread.currentThread(),mode); //Trythefastpathofenq;backuptofullenqonfailure Nodepred=tail; if(pred!=null){ node.prev=pred; if(compareAndSetTail(pred,node)){ pred.next=node; returnnode; } } enq(node); returnnode; }
这个方法的注释:创建一个入队node为当前线程,Node.EXCLUSIVE是独占锁,Node.SHARED是共享锁。
先找到等待队列的tail节点pred,如果pred!=null,就把当前线程添加到pred后面进入等待队列,如果不存在tail节点执行enq()
privateNodeenq(finalNodenode){ for(;;){ Nodet=tail; if(t==null){//Mustinitialize if(compareAndSetHead(newNode())) tail=head; }else{ node.prev=t; if(compareAndSetTail(t,node)){ t.next=node; returnt; } } } }
这里进行了循环,如果此时存在了tail就执行同上一步骤的添加队尾操作,如果依然不存在,就把当前线程作为head结点。
插入节点后,调用acquireQueued()进行阻塞
acquireQueued()
finalbooleanacquireQueued(finalNodenode,intarg){ booleanfailed=true; try{ booleaninterrupted=false; for(;;){ finalNodep=node.predecessor(); if(p==head&&tryAcquire(arg)){ setHead(node); p.next=null;//helpGC failed=false; returninterrupted; } if(shouldParkAfterFailedAcquire(p,node)&& parkAndCheckInterrupt()) interrupted=true; } }finally{ if(failed) cancelAcquire(node); } }
先获取当前节点的前一节点p,如果p是head的话就再进行一次tryAcquire(arg)操作,如果成功就返回,否则就执行shouldParkAfterFailedAcquire、parkAndCheckInterrupt来达到阻塞效果;
以上所述是小编给大家介绍的tryAcquire()、addWaiter()、acquireQueued()的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!