详解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()的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!