当前位置: 首页 > 后端技术 > Java

[JUC]一张图看懂ReentrantLock的添加和解锁逻辑

时间:2023-04-01 15:55:00 Java

使用示例ThreadA,ThreadB,ThreadC访问如下逻辑ReentrantLocklock=newReentrantLock();//==1.Locklock.lock();。..省略业务处理...//==2.释放lock.unlock();不公平加锁过程是公平的,没有ThreadD的一些逻辑,直接入队。后续会详细解释这张图。Lock1.State修改//##State:访问线程会以cas的形式修改state的值,锁处理0->1privatevolatileintstate;//##Holdthethread:线程状态修改成功后为Record。例如exclusiveOwnerThread=ThreadAprivatetransientThreadexclusiveOwnerThread;#NonfairSyncfairimplementationfinalvoidlock(){//==1.casmodifystatestate0->1(queuejump1)if(compareAndSetState(0,1))//state修改成功修改持有线程exclusiveOwnerThread=ThreadAsetExclusiveOwnerThread(Thread.currentThread());else//==2.构建队列并阻塞线程acquire(1);}2.构建队列###publicfinalvoidacquire(intarg){//a-尝试获取,尝试修改状态state(获取不成功继续后续逻辑)独占),arg))selfInterrupt();}a-尝试获取(可能排队的位置)java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquirejava.util.concurrent.locks.ReentrantLock。Sync#nonfairTryAcquirefinalbooleannonfairTryAcquire(intacquires){finalThreadcurrent=Thread.currentThread();intc=getState();//##队列位置if(c==0){if(比较AndSetState(0,acquires)){setExclusiveOwnerThread(current);返回真;}}//##可重入,state++elseif(current==getExclusiveOwnerThread()){intnextc=c+acquires;if(nextc<0)//溢出thrownewError("Maximumlockcountexceeded");设置状态(下一步);返回真;}returnfalse;}b1-添加等待节点,构建“独占”模式队列classNode{/**Exclusive*/staticfinalNodeEXCLUSIVE=null;//指向线程volatileThreadthread;易变节点上一个;接下来是可变节点;staticfinalintSIGNAL=-1;java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiterprivateNodeaddWaiter(Nodemode){Nodenode=newNode(Thread.currentThread(),模式);//尝试enq的快速路径;在节点pred=tail发生故障时备份到完整enq;//==2.队列不为空,节点尾插if(pred!=null){node.prev=pred;if(compareAndSetTail(pred,node)){pred.next=n颂;返回节点;}}//==1.初始队列构造enq(node);返回节点;//返回尾节点}//==1.初始队列构造java.util.concurrent.locks.AbstractQueuedSynchronizer#enqprivateNodeenq(finalNodenode){for(;;){Nodet=tail;//--A、初始构造,头尾指针指向空节点if(t==null){if(compareAndSetHead(newNode()))tail=head;}//--B,尾部插入else{node.prev=t;//cas修改尾节点的点if(compareAndSetTail(t,node)){t.next=node;返回吨;//返回头节点}}}}b2-queue获取java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueuedfinalbooleanacquireQueued(finalNodenode,intarg){booleanfailed=true;尝试{布尔中断=false;//在循环中for(;;){finalNodep=node.predecessor();//###前驱节点为头节点,有机会尝试获取//(结合下一个if判断,会自旋两次,也就是说有两次尝试获取本机是的)if(p==head&&tryAcquire(arg)){setHead(node);p.next=null;//帮助GCfailed=false;返回中断;}//###第一次设置waitstatussignal返回false//###第二次判断waitstatus==signal返回trueif(shouldParkAfterFailedAcquire(p,node)//===线程阻塞(从这里继续执行将来醒来时)&&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=节点;}//--第一行调用else{compareAndSetWaitStatus(pred,ws,节点信号);}returnfalse;}===privatefinalbooleanparkAndCheckInterrupt(){LockSupport.park(this);//当前线程是否中断returnThread.interrupted();}二、释放java.util.concurrent.locks.ReentrantLock#unlockjava.util.concurrent.locks.AbstractQueuedSynchronizer#release{//==1.状态恢复,exclusiveOwnerThreadclearif(tryRelease(arg)){Nodeh=head;if(h!=null&&h.waitStatus!=0)//==2.“解除阻塞”成功执行节点unparkSuccessor(h);返回真;}returnfalse;}1.状态恢复,exclusiveOwnerThread清空protectedfinalbooleantryRelease(intreleases){//加锁时线程重入,state++因此,解锁时,state--intc=getState()-releases;if(Thread.currentThread()!=getExclusiveOwnerThread())thrownewIllegalMonitorStateException();布尔自由=假;//当状态返回0时,释放线程引用if(c==0){free=true;setExclusiveOwnerThread(null);}设置状态(c);returnfree;}2.“Unblock”成功执行nodeprivatevoidunparkSuccessor(Nodenode){intws=node.等待状态;//加锁时,ws=SIGNAL,即-1。现在更改为0if(ws<0)compareAndSetWaitStatus(node,ws,0);/**要取消停放的线程在后继者中举行,通常*只是下一个节点。但如果取消或明显为空,*从尾部向后遍历以找到实际*未取消的后继者。*/节点s=node.next;如果(s==null||s.waitStatus>0){s=null;for(Nodet=tail;t!=null&&t!=node;t=t.prev)if(t.waitStatus<=0)s=t;}//##释放s节点,它是head的下一个节点if(s!=null)LockSupport。unpark(s.thread);}3.公平锁区别1#FairSyncfairimplementationfinalvoidlock(){//没有跳队操作,直接建队列acquire(1);}和刚才的unfairimplementation比较,只有elsepart#NonfairSyncunfairimplementationfinalvoidlock(){//==1.cas修改状态state0->1(跳队列1)if(compareAndSetState(0,1))//状态修改成功修改持有线程exclusiveOwnerThread=ThreadAsetExclusiveOwnerThread(Thread.currentThread());###fair实现只有这部分逻辑else//==2.建立队列并阻塞线程acquire(1);}区别2publicfinalvoidacquire(intarg){if(!tryAcquire(arg)&&acquireQueued(addWaiter(Node.EXCLUSIVE),arg))selfInterrupt();}protectedfinalbooleantryAcquire(intacquires){finalThreadcurrent=Thread.currentThread();intc=getState();if(c==0){//###公平实现(more!hasQueuedPredecessors()):不需要排队才有资格进行后续的cas操作if(!hasQueuedPredecessors()&&compareAndSetState(0,acquires)){setExclusiveOwnerThread(当前的);返回真;}}elseif(current==getExclusiveOwnerThread()){intnextc=c+acquires;if(nextc<0)thrownewError("超过最大锁计数");设置状态(下一步);返回真;}返回假;}}