µ±Ç°Î»ÖãºÖ÷Ò³ > ²é¿´ÄÚÈÝ

ÉîÈëÁ˽âReentrantLockÖеĹ«Æ½ËøºÍ·Ç¹«Æ½ËøµÄ¼ÓËø»úÖÆ

·¢²¼Ê±¼ä£º2021-07-14 00:00| ÓРλÅóÓѲ鿴

¼ò½é£ºËÍ´ó¼ÒÒÔÏÂjavaѧϰ×ÊÁÏ£¬ÎÄÄ©ÓÐÁìÈ¡·½Ê½ Ç°ÑÔ ReentrantLockºÍsynchronizedÒ»Ñù¶¼ÊÇʵÏÖÏß³Ìͬ²½£¬µ«ÊÇÏñ±ÈsynchronizedËü¸ü¼ÓÁé»î¡¢Ç¿´ó¡¢Ôö¼ÓÁËÂÖѯ¡¢³¬Ê±¡¢Öжϵȸ߼¶¹¦ÄÜ£¬¿ÉÒÔ¸ü¼Ó¾«Ï¸»¯µÄ¿ØÖÆÏß³Ìͬ²½£¬ËüÊÇ»ùÓÚAQSʵÏÖµÄËø£¬ËûÖ§³Ö¹«Æ½ËøºÍ·Ç¹«Æ½Ëø¡­¡­

ËÍ´ó¼ÒÒÔÏÂjavaѧϰ×ÊÁÏ£¬ÎÄÄ©ÓÐÁìÈ¡·½Ê½




Ç°ÑÔ

ReentrantLockºÍsynchronizedÒ»Ñù¶¼ÊÇʵÏÖÏß³Ìͬ²½£¬µ«ÊÇÏñ±ÈsynchronizedËü¸ü¼ÓÁé»î¡¢Ç¿´ó¡¢Ôö¼ÓÁËÂÖѯ¡¢³¬Ê±¡¢Öжϵȸ߼¶¹¦ÄÜ£¬¿ÉÒÔ¸ü¼Ó¾«Ï¸»¯µÄ¿ØÖÆÏß³Ìͬ²½£¬ËüÊÇ»ùÓÚAQSʵÏÖµÄËø£¬ËûÖ§³Ö¹«Æ½ËøºÍ·Ç¹«Æ½Ëø£¬Í¬Ê±ËûÒ²ÊÇ¿ÉÖØÈëËøºÍ×ÔÐýËø¡£

±¾Õ½«»ùÓÚÔ´ÂëÀ´Ì½Ë÷Ò»ÏÂReentrantLockµÄ¼ÓËø»úÖÆ£¬ÎÄÖÐÈç¹û´æÔÚÀí½â²»µ½Î»µÄµØ·½£¬»¹ÇëÌá³ö±¦¹óÒâ¼û¹²Í¬Ì½ÌÖ£¬²»Áߴͽ̡£

¹«Æ½ËøºÍ·Ç¹«Æ½ËøµÄ¼ÓËø»úÖÆÁ÷³Ìͼ£º

ͼƬ

Ò»¡¢ReentrantLockµÄ¹«Æ½Ëø

ʹÓÃReentrantLockµÄ¹«Æ½Ëø£¬µ÷ÓÃlock½øÐмÓËø£¬lock·½·¨µÄÔ´ÂëÈçÏ£º

`final?void?lock()?{`
 `acquire(1);`
`}`
`public?final?void?acquire(int?arg)?{`
 `if?(!tryAcquire(arg)?&&`
 `acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))`
 `selfInterrupt();`
`}`

¿ÉÒÔ¿´µ½£¬FairLockÊ×Ïȵ÷ÓÃÁËtryAcquire,tryAcquireÔ´ÂëÈçÏ£º

`/**`
 `*?Fair?version?of?tryAcquire.??Don't?grant?access?unless`
 `*?recursive?call?or?no?waiters?or?is?first.`
 `*/`
`protected?final?boolean?tryAcquire(int?acquires)?{`
 `final?Thread?current?=?Thread.currentThread();`
 `int?c?=?getState();`
 `if?(c?==?0)?{`
 `//Èç¹û¶ÓÁÐÖв»´æÔڵȴýµÄÏ̻߳òÕßµ±Ç°Ïß³ÌÔÚ¶ÓÁÐÍ·²¿£¬Ôò»ùÓÚCAS½øÐмÓËø`
 `if?(!hasQueuedPredecessors()?&&`
 `compareAndSetState(0,?acquires))?{`
 `setExclusiveOwnerThread(current);`
 `return?true;`
 `}`
 `}`
 `//ÊÇ·ñ¿ÉÒÔ½øÐÐËøÖØÈë`
 `else?if?(current?==?getExclusiveOwnerThread())?{`
 `int?nextc?=?c?+?acquires;`
 `if?(nextc?<?0)`
 `throw?new?Error("Maximum?lock?count?exceeded");`
 `setState(nextc);`
 `return?true;`
 `}`
 `return?false;`
`}`

´ÓÔ´ÂëÖпÉÒÔ¿´µ½£¬µ±stateΪ0£¬¼´Ã»ÓÐÏ̻߳ñÈ¡µ½Ëøʱ£¬FairLockÊ×ÏÈ»áµ÷ÓÃhasQueuedPredecessors()·½·¨¼ì²é¶ÓÁÐÖÐÊÇ·ñÓеȴýµÄÏ̻߳òÕß×Ô¼ºÊÇ·ñÔÚ¶ÓÁÐÍ·²¿£¬Èç¹û¶ÓÁÐÖв»´æÔڵȴýµÄÏ̻߳òÕß×Ô¼ºÔÚ¶ÓÁÐÍ·²¿Ôòµ÷ÓÃcompareAndSetState()·½·¨»ùÓÚCAS²Ù×÷½øÐмÓËø£¬Èç¹ûCAS²Ù×÷³É¹¦£¬Ôòµ÷ÓÃsetExclusiveOwnerThreadÉèÖüÓËøÏß³ÌΪµ±Ç°Ï̡߳£

µ±state²»Îª0£¬¼´ÓÐÏß³ÌÕ¼ÓÃËøµÄʱºò»áÅжÏÕ¼ÓÐËøµÄÏß³ÌÊÇ·ñÊǵ±Ç°Ị̈߳¬Èç¹ûÊǵĻ°Ôò¿ÉÒÔÖ±½Ó»ñÈ¡µ½Ëø£¬Õâ¾ÍÊÇReentrantLockÊÇ¿ÉÖØÈëËøµÄÌåÏÖ¡£

Èç¹ûͨ¹ýµ÷ÓÃtryAcquireûÓлñÈ¡µ½Ëø£¬´ÓÔ´ÂëÖÐÎÒÃÇ¿ÉÒÔ¿´µ½£¬FairLock»áµ÷ÓÃaddWaiter()·½·¨½«µ±Ç°Ï̼߳ÓÈëCLH¶ÓÁÐÖУ¬addWaiter·½·¨Ô´ÂëÈçÏ£º

`private?Node?addWaiter(Node?mode)?{`
 `Node?node?=?new?Node(Thread.currentThread(),?mode);`
 `//?Try?the?fast?path?of?enq;?backup?to?full?enq?on?failure`
 `Node?pred?=?tail;`
 `if?(pred?!=?null)?{`
 `node.prev?=?pred;`
 `//»ùÓÚCAS½«µ±Ç°Ï߳̽ڵã¼ÓÈë¶ÓÁÐβ²¿`
 `if?(compareAndSetTail(pred,?node))?{`
 `pred.next?=?node;`
 `return?node;`
 `}`
 `}`
 `//Èç¹ûCAS²Ù×÷ʧ°Ü£¬Ôòµ÷ÓÃenq×ÔÐý¼ÓÈë¶ÓÁÐ`
 `enq(node);`
 `return?node;`
`}`
`private?Node?enq(final?Node?node)?{`
 `for?(;;)?{`
 `Node?t?=?tail;`
 `if?(t?==?null)?{?//?Must?initialize`
 `if?(compareAndSetHead(new?Node()))`
 `tail?=?head;`
 `}?else?{`
 `node.prev?=?t;`
 `if?(compareAndSetTail(t,?node))?{`
 `t.next?=?node;`
 `return?t;`
 `}`
 `}`
 `}`
 `}`

ÔÚaddWaiter·½·¨ÖУ¬»áCAS²Ù×÷½«µ±Ç°Ï߳̽ڵã¼ÓÈë¶ÓÁÐβ²¿£¬Èç¹ûµÚÒ»´ÎCASʧ°Ü£¬Ôò»áµ÷ÓÃenq·½·¨Í¨¹ý×ÔÐýµÄ·½Ê½£¬¶à´Î³¢ÊÔ½øÐÐCAS²Ù×÷½«µ±Ç°Ï̼߳ÓÈë¶ÓÁС£

½«µ±Ç°Ï̼߳ÓÈë¶ÓÁÐÖ®ºó£¬»áµ÷ÓÃacquireQueued·½·¨ÊµÏÖ[µ±Ç°Ïß³Ì]µÄ×ÔÐý¼ÓËø£¬acquireQueuedÔ´ÂëÈçÏ£º

`final?boolean?acquireQueued(final?Node?node,?int?arg)?{`
 `boolean?failed?=?true;`
 `try?{`
 `boolean?interrupted?=?false;`
 `for?(;;)?{`
 `final?Node?p?=?node.predecessor();`
 `if?(p?==?head?&&?tryAcquire(arg))?{`
 `setHead(node);`
 `p.next?=?null;?//?help?GC`
 `failed?=?false;`
 `return?interrupted;`
 `}`
 `if?(shouldParkAfterFailedAcquire(p,?node)?&&`
 `parkAndCheckInterrupt())`
 `interrupted?=?true;`
 `}`
 `}?finally?{`
 `if?(failed)`
 `cancelAcquire(node);`
 `}`
 `}`

ÔÚacquireQueued·½·¨ÖÐÿ´Î×ÔÐýÊ×ÏÈ»áµ÷ÓÃpredecessor()·½·¨»ñÈ¡£¬µ±Ç°Ï߳̽ڵãµÄÇ°½Úµã£¬Èç¹û·¢ÏÖÇ°½ÚµãÊÇhead½Úµã£¬Ôò˵Ã÷µ±Ç°Ï߳̽ڵ㴦ÓÚ¶ÔÍ·£¨headÊÇ¿þÀܽڵ㣩£¬ÄÇôÔòµ÷ÓÃtryAcquire¾¡ÐļÓËø¡£

Èç¹ûµ±Ç°Ï߳̽ڵ㲻ÔÚ¶ÓÁÐÍ·²¿£¬ÄÇôÔò»áµ÷ÓÃshouldParkAfterFailedAcquire·½·¨Åжϵ±Ç°Ï߳̽ڵãÊÇ·ñ¿ÉÒÔ¹ÒÆðÖªµÀÇ°½ÚµãÊÍ·ÅËøʱ»½ÐÑ×Ô¼º£¬Èç¹û¿ÉÒÔ¹ÒÆð£¬Ôòµ÷ÓÃparkAndCheckInterruptʵÏÖ¹ÒÆð²Ù×÷¡£ÁíÍ⣬¹Ø×¢ºó¶Ë¼Ü¹¹Ê¦¹«Öںţ¬»Ø¸´¡°ÃæÊÔ¡±£¬ËÍÄãÒ»·ÝÃæÊÔÌⱦµä£¡

shouldParkAfterFailedAcquireÔ´ÂëÈçÏ£º

`private?static?boolean?shouldParkAfterFailedAcquire(Node?pred,?Node?node)?{`
 `int?ws?=?pred.waitStatus;`
 `if?(ws?==?Node.SIGNAL)`
 `/*`
 `*?This?node?has?already?set?status?asking?a?release`
 `*?to?signal?it,?so?it?can?safely?park.`
 `*/`
 `return?true;`
 `if?(ws?>?0)?{`
 `/*`
 `*?Predecessor?was?cancelled.?Skip?over?predecessors?and`
 `*?indicate?retry.`
 `*/`
 `do?{`
 `node.prev?=?pred?=?pred.prev;`
 `}?while?(pred.waitStatus?>?0);`
 `pred.next?=?node;`
 `}?else?{`
 `/*`
 `*?waitStatus?must?be?0?or?PROPAGATE.??Indicate?that?we`
 `*?need?a?signal,?but?don't?park?yet.??Caller?will?need?to`
 `*?retry?to?make?sure?it?cannot?acquire?before?parking.`
 `*/`
 `compareAndSetWaitStatus(pred,?ws,?Node.SIGNAL);`
 `}`
 `return?false;`
 `}`

shouldParkAfterFailedAcquireÔ´ÂëÖУ¬Èç¹ûµ±Ç°Ï߳̽ڵãµÄÇ°½ÚµãµÄwaitStatus״̬ΪSIGNAL£¨-1£©Ê±£¬±íÃ÷Ç°½ÚµãÒѾ­ÉèÖÃÁËÊÍ·ÅËøʱ»½ÐÑ£¨unpark£©ËüµÄºó½Úµã£¬ÄÇôµ±Ç°Ï߳̽ڵã¿ÉÒÔ°²ÐÄ×èÈû£¨park£©£¬µÈ´ýËüµÄÇ°½ÚµãÔÚunlockʱ»½ÐÑ×Ô¼º¼ÌÐø³¢ÊÔ¼ÓËø¡£

Èç¹ûÇ°½ÚµãµÄwaitStatus״̬>0,¼´ÎªCANCELLED (1)£¬±íÃ÷Ç°½ÚµãÒѾ­·ÅÆúÁË»ñÈ¡Ëø£¬ÄÇôÔò»á¼ÌÐøÍùÇ°ÕÒ£¬ÕÒµ½Ò»¸öÄܹ»ÔÚunlockʱ»½ÐÑ×Ô¼ºµÄÏ߳̽ڵãΪֹ¡£Èç¹ûÇ°½ÚµãwaitStatus״̬ÊÇCONDITION £¨-2£©£¬¼´´¦ÓڵȴýÌõ¼þµÄ״̬£¬Ôò»á»ùÓÚCAS³¢ÊÔÉèÖÃÇ°½Úµã״̬ΪSIGNAL£¨Ö÷¶¯¸ÉԤǰ½Úµã´ïµ½»½ÐÑ×Ô¼ºµÄÄ¿µÄ£©¡£

parkAndCheckInterruptÔ´Â룺

`private?final?boolean?parkAndCheckInterrupt()?{`
 `LockSupport.park(this);`
 `return?Thread.interrupted();`
 `}`

¶þ¡¢ReentrantLockµÄ·Ç¹«Æ½Ëø

ºÍ¹«Æ½Ëø¼ÓËø»úÖƲ»Í¬µÄÊÇ£¬·Ç¹«Æ½ËøÒ»ÉÏÀ´²»¹Ü¶ÓÁÐÖÐÊÇ·ñ»¹´æÔÚỊ̈߳¬¾ÍÖ±½ÓʹÓÃCAS²Ù×÷½øÐг¢ÊÔ¼ÓËø£¨Õâ¾ÍÊÇËüµÄ·Ç¹«Æ½µÄÌåÏÖ£©£¬Ô´ÂëÈçÏ£º

 `final?void?lock()?{`
 `if?(compareAndSetState(0,?1))`
 `setExclusiveOwnerThread(Thread.currentThread());`
 `else`
 `acquire(1);`
`}`
`public?final?void?acquire(int?arg)?{`
 `if?(!tryAcquire(arg)?&&`
 `acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))`
 `selfInterrupt();`
`}`

Èç¹ûCAS²Ù×÷ʧ°Ü£¨Ò»ÉÏÀ´¾Í³ÔÁ˸ö±Õßþ£©£¬Ôòµ÷ÓÃacquire·½·¨½øÐкóÐøµÄ³¢ÊԺ͵ȴý¡£´ÓÔ´ÂëÖпÉÒÔ¿´µ½£¬Ê×ÏȻص÷ÓÃtryAcquire·½·¨½øÐÐÔٴγ¢ÊÔ¼ÓËø»òÕßËøÖØÈ룬NoFairLockdµÄtryAcquire·½·¨Ô´ÂëÈçÏ£º

`final?boolean?nonfairTryAcquire(int?acquires)?{`
 `final?Thread?current?=?Thread.currentThread();`
 `int?c?=?getState();`
 `if?(c?==?0)?{`
 `if?(compareAndSetState(0,?acquires))?{`
 `setExclusiveOwnerThread(current);`
 `return?true;`
 `}`
 `}`
 `else?if?(current?==?getExclusiveOwnerThread())?{`
 `int?nextc?=?c?+?acquires;`
 `if?(nextc?<?0)?//?overflow`
 `throw?new?Error("Maximum?lock?count?exceeded");`
 `setState(nextc);`
 `return?true;`
 `}`
 `return?false;`
 `}`

¿ÉÒÔ¿´µ½NoFairLockµÄtryAcquire·½·¨ºÍFairLockµÄtryAcquire·½·¨Î¨Ò»²»Í¬Ö®´¦ÊÇNoFairLockÖг¢ÊÔ¼ÓËøÇ°²»ÐèÒªµ÷ÓÃhasQueuedPredecessors·½·¨Åж϶ÓÁÐÖÐÊÇ·ñ´æÔÚÆäËûỊ̈߳¬¶øÊÇÖ±½Ó½øÐÐCAS²Ù×÷¼ÓËø¡£

ÄÇôÈç¹ûÔٴγ¢ÊÔ¼ÓËø»òÕßËøÖØÈëʧ°Ü£¬Ôò»á½øÐкóÐøµÄºÍ¹«Æ½ËøÍêÈ«Ò»ÑùµÄ²Ù×÷Á÷³Ì£¨²»ÔÙ׸Êö£©£¬¼´£º¼ÓÈë¶ÓÁУ¨addWaiter£©¨C>×ÔÐý¼ÓËø(acquireQueued)¡£

Èý¡¢unlock½âËø

˵ÍêÁ˹«Æ½ËøºÍ·Ç¹«Æ½ËøµÄ¼ÓËø»úÖÆ£¬ÎÒÃÇÔÙ˳´ø¼òµ¥µÄ¿´¿´½âËøÔ´Âë¡£unlockÔ´ÂëÈçÏ£º

`public?void?unlock()?{`
 `sync.release(1);`
`}`
`public?final?boolean?release(int?arg)?{`
 `//³¢ÊÔÊÍ·ÅËø`
 `if?(tryRelease(arg))?{`
 `Node?h?=?head;`
 `//ËøÊͷųɺó»½ÐѺó±ß×èÈûµÄÏ߳̽ڵã`
 `if?(h?!=?null?&&?h.waitStatus?!=?0)`
 `unparkSuccessor(h);`
 `return?true;`
 `}`
 `return?false;`
`}`

×Ü½á ±¾ÎÄÖ÷Ҫ̽Ë÷Á˹«Æ½ËøºÍ·Ç¹«Æ½ËøµÄ¼ÓËøÁ÷³Ì£¬ËûÃÇ»ñÈ¡ËøµÄ²»Í¬µãºÍÏàͬµã¡£ÕûƪÎÄÕÂÉæ¼°µ½ÁËÒÔϼ¸µã£º

  1. ¹«Æ½Ëø¡¢·Ç¹«Æ½Ëø¼ÓËø¹ý³Ì
  2. ×ÔÐýËøµÄʵÏÖÒÔ¼°×ÔÐý¹ý³ÌÖеÄ×èÈû»½ÐÑ
  3. ¿ÉÖØÈëËøµÄʵÏÖ
  4. CLH¶ÓÁÐ

×¢£ºÎÄÖÐÈç¹û´æÔÚÀí½â²»µ½Î»µÄµØ·½»¹ÇëÌá³ö±¦¹óÒâ¼û£¬²»Áߴͽ̡£


±¾ÎÄת×ÔÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬Ô­ÎÄÁ´½Ó£ºhttps://segmentfault.com/a/1190000040345696
±¾Õ¾²¿·ÖÄÚÈÝתÔØÓÚÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬×ªÔØ֮ĿµÄÔÚÓÚ´«²¥¸ü¶àÓÅÐã¼¼ÊõÄÚÈÝ£¬ÈçÓÐÇÖȨÇëÁªÏµQQ/΢ÐÅ£º153890879ɾ³ý£¬Ð»Ð»£¡

ÍƼöͼÎÄ

  • ÖÜÅÅÐÐ
  • ÔÂÅÅÐÐ
  • ×ÜÅÅÐÐ

Ëæ»úÍƼö