当前位置: 首页>后端>正文

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三)

鑻嶇┕涔嬭竟锛屾旦鐎氫箣鎸氾紝鐪版仸涔嬬編锛?鎮熷績鎮熸€э紝鍠勫鍠勭粓锛屾儫鍠勬儫閬擄紒 鈥斺€?鏈濇Э銆婃湞妲垮叜骞磋銆?/p>

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第1张

鍐欏湪寮€澶?/h2>
Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第2张

鍦ㄥ苟鍙戠紪绋嬮鍩燂紝鏈変袱澶ф牳蹇冮棶棰橈細涓€涓槸浜掓枼锛屽嵆鍚屼竴鏃跺埢鍙厑璁镐竴涓嚎绋嬭闂叡浜祫婧愶紱鍙︿竴涓槸鍚屾锛屽嵆绾跨▼涔嬮棿濡備綍閫氫俊銆佸崗浣溿€?lt;br />涓昏鍘熷洜鏄紝瀵逛簬澶氱嚎绋嬪疄鐜板疄鐜板苟鍙戯紝涓€鐩翠互鏉ワ紝澶氱嚎绋嬮兘瀛樺湪2涓棶棰橈細

  • 绾跨▼涔嬮棿鍐呭瓨鍏变韩锛岄渶瑕侀€氳繃鍔犻攣杩涜鎺у埗锛屼絾鏄姞閿佷細瀵艰嚧鎬ц兘涓嬮檷锛屽悓鏃跺鏉傜殑鍔犻攣鏈哄埗涔熶細澧炲姞缂栫▼缂栫爜闅惧害
  • 杩囧绾跨▼閫犳垚绾跨▼涔嬮棿鐨勪笂涓嬫枃鍒囨崲锛屽鑷存晥鐜囦綆涓?/li>

鍥犳锛屽湪骞跺彂缂栫▼棰嗗煙涓紝涓€鐩存湁涓€涓緢閲嶈鐨勮璁″師鍒欙細 鈥?涓嶈閫氳繃鍐呭瓨鍏变韩鏉ュ疄鐜伴€氫俊锛岃€屽簲璇ラ€氳繃閫氫俊鏉ュ疄鐜板唴瀛樺叡浜€傗€?lt;br />绠€鍗曟潵璇达紝灏辨槸灏藉彲鑳介€氳繃娑堟伅閫氫俊锛岃€屼笉鏄唴瀛樺叡浜潵瀹炵幇杩涚▼鎴栬€呯嚎绋嬩箣闂寸殑鍚屾銆?/p>

鍏冲仴鏈

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第3张

<br />鏈枃鐢ㄥ埌鐨勪竴浜涘叧閿瘝璇互鍙婂父鐢ㄦ湳璇紝涓昏濡備笅锛?/p>

  • 骞跺彂(Concurrent): 鍦ㄦ搷浣滅郴缁熶腑锛屾槸鎸囦竴涓椂闂存涓湁鍑犱釜绋嬪簭閮藉浜庡凡鍚姩杩愯鍒拌繍琛屽畬姣曚箣闂达紝涓旇繖鍑犱釜绋嬪簭閮芥槸鍦ㄥ悓涓€涓鐞嗘満涓婅繍琛屻€?/li>
  • 骞惰(Parallel): 褰撶郴缁熸湁涓€涓互涓奀PU鏃讹紝褰撲竴涓狢PU鎵ц涓€涓繘绋嬫椂锛屽彟涓€涓狢PU鍙互鎵ц鍙︿竴涓繘绋嬶紝涓や釜杩涚▼浜掍笉鎶㈠崰CPU璧勬簮锛屽彲浠ュ悓鏃惰繘琛屻€?/li>
  • 淇″彿閲?Semaphore): 鏄湪澶氱嚎绋嬬幆澧冧笅浣跨敤鐨勪竴绉嶈鏂斤紝鏄彲浠ョ敤鏉ヤ繚璇佷袱涓垨澶氫釜鍏抽敭浠g爜娈典笉琚苟鍙戣皟鐢紝涔熸槸浣滅郴缁熺敤鏉ヨВ鍐冲苟鍙戜腑鐨勪簰鏂ュ拰鍚屾闂鐨勪竴绉嶆柟娉曘€?/li>
  • 淇″彿閲忔満鍒?Semaphores)锛?鐢ㄦ潵瑙e喅鍚屾/浜掓枼鐨勯棶棰樼殑锛屽畠鏄?965骞?鑽峰叞瀛﹁€?Dijkstra鎻愬嚭浜嗕竴绉嶅崜鏈夋垚鏁堢殑瀹炵幇杩涚▼浜掓枼涓庡悓姝ョ殑鏂规硶銆?/li>
  • 绠$▼(Monitor) : 涓€鑸槸鎸囩鐞嗗叡浜彉閲忎互鍙婂鍏变韩鍙橀噺鐨勬搷浣滆繃绋嬶紝璁╁畠浠敮鎸佸苟鍙戠殑涓€绉嶆満鍒躲€?/li>
  • 浜掓枼(Mutual Exclusion)锛氫竴涓叕鍏辫祫婧愬悓涓€鏃跺埢鍙兘琚竴涓繘绋嬫垨绾跨▼浣跨敤锛屽涓繘绋嬫垨绾跨▼涓嶈兘鍚屾椂浣跨敤鍏叡璧勬簮銆傚嵆灏辨槸鍚屼竴鏃跺埢鍙厑璁镐竴涓嚎绋嬭闂叡浜祫婧愮殑闂銆?/li>
  • 鍚屾(Synchronization)锛氫袱涓垨涓や釜浠ヤ笂鐨勮繘绋嬫垨绾跨▼鍦ㄨ繍琛岃繃绋嬩腑鍗忓悓姝ヨ皟锛屾寜棰勫畾鐨勫厛鍚庢搴忚繍琛屻€傚嵆灏辨槸绾跨▼涔嬮棿濡備綍閫氫俊銆佸崗浣滅殑闂銆?/li>
  • 瀵硅薄姹?Object Pool): 鎸囩殑鏄竴娆℃€у垱寤哄嚭 N 涓璞★紝涔嬪悗鎵€鏈夌殑绾跨▼閲嶅鍒╃敤杩?N 涓璞★紝褰撶劧瀵硅薄鍦ㄨ閲婃斁鍓嶏紝涔熸槸涓嶅厑璁稿叾浠栫嚎绋嬩娇鐢ㄧ殑, 涓€鑸寚淇濆瓨瀹炰緥瀵硅薄鐨勫鍣ㄣ€?/li>

鍩烘湰姒傝堪

鍦↗ava棰嗗煙涓紝鎴戜滑鍙互灏嗛攣澶ц嚧鍒嗕负鍩轰簬Java璇硶灞傞潰(鍏抽敭璇?瀹炵幇鐨勯攣鍜屽熀浜嶫DK灞傞潰瀹炵幇鐨勯攣銆?/p>

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第4张

鍦↗ava棰嗗煙涓? 灏ゅ叾鏄湪骞跺彂缂栫▼棰嗗煙锛屽浜庡绾跨▼骞跺彂鎵ц涓€鐩存湁涓ゅぇ鏍稿績闂锛氬悓姝ュ拰浜掓枼銆傚叾涓細

  • 浜掓枼(Mutual Exclusion)锛氫竴涓叕鍏辫祫婧愬悓涓€鏃跺埢鍙兘琚竴涓繘绋嬫垨绾跨▼浣跨敤锛屽涓繘绋嬫垨绾跨▼涓嶈兘鍚屾椂浣跨敤鍏叡璧勬簮銆傚嵆灏辨槸鍚屼竴鏃跺埢鍙厑璁镐竴涓嚎绋嬭闂叡浜祫婧愮殑闂銆?/li>
  • 鍚屾(Synchronization)锛氫袱涓垨涓や釜浠ヤ笂鐨勮繘绋嬫垨绾跨▼鍦ㄨ繍琛岃繃绋嬩腑鍗忓悓姝ヨ皟锛屾寜棰勫畾鐨勫厛鍚庢搴忚繍琛屻€傚嵆灏辨槸绾跨▼涔嬮棿濡備綍閫氫俊銆佸崗浣滅殑闂銆?/li>

閽堝瀵逛簬杩欎袱澶ф牳蹇冮棶棰橈紝鍒╃敤绠$▼鏄兘澶熻В鍐冲拰瀹炵幇鐨勶紝鍥犳鍙互璇达紝绠$▼鏄苟鍙戠紪绋嬬殑涓囪兘閽ュ寵銆?lt;br />铏界劧锛孞ava鍦ㄥ熀浜庤娉曞眰闈?synchronized 鍏抽敭瀛?瀹炵幇浜嗗绠$▼鎶€鏈?浣嗘槸浠庝娇鐢ㄦ柟寮忓拰鎬ц兘涓婃潵璇达紝鍐呯疆閿?synchronized 鍏抽敭瀛?鐨勭矑搴︾浉瀵硅繃澶э紝涓嶆敮鎸佽秴鏃跺拰涓柇绛夐棶棰樸€?lt;br />涓轰簡寮ヨˉ杩欎簺闂锛屼粠JDK灞傞潰瀵瑰叾鈥滈噸澶嶉€犺疆瀛愨€濓紝鍦↗DK鍐呴儴瀵瑰叾閲嶆柊璁捐鍜屽畾涔夛紝鐢氳嚦瀹炵幇浜嗘柊鐨勭壒鎬с€?lt;br />鍦↗ava棰嗗煙涓紝浠嶫DK婧愮爜鍒嗘瀽鏉ョ湅锛屽熀浜嶫DK灞傞潰瀹炵幇鐨勯攣澶ц嚧涓昏鍙互鍒嗕负浠ヤ笅4绉嶆柟寮忥細

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第5张
  • 鍩轰簬Lock鎺ュ彛瀹炵幇鐨勯攣锛欽DK1.5鐗堟湰鎻愪緵鐨凴eentrantLock绫?/li>
  • 鍩轰簬ReadWriteLock鎺ュ彛瀹炵幇鐨勯攣锛欽DK1.5鐗堟湰鎻愪緵鐨凴eentrantReadWriteLock绫?/li>
  • 鍩轰簬AQS鍩虹鍚屾鍣ㄥ疄鐜扮殑閿侊細JDK1.5鐗堟湰鎻愪緵鐨勫苟鍙戠浉鍏崇殑鍚屾鍣⊿emaphore锛孋yclicBarrier浠ュ強CountDownLatch绛?/li>
  • 鍩轰簬鑷畾涔堿PI鎿嶄綔瀹炵幇鐨勯攣锛欽DK1.8鐗堟湰涓彁渚涚殑StampedLock绫?/li>

浠庨槄璇绘簮鐮佷笉闅惧彂鐜帮紝鍦↗ava SDK 骞跺彂鍖呬富瑕侀€氳繃AbstractQueuedSynchronizer(AQS)瀹炵幇澶氱嚎绋嬪悓姝ユ満鍒剁殑灏佽涓庡畾涔夛紝鑰岄€氳繃Lock 鍜?Condition 涓や釜鎺ュ彛鏉ュ疄鐜扮绋嬶紝鍏朵腑 Lock 鐢ㄤ簬瑙e喅浜掓枼闂锛孋ondition 鐢ㄤ簬瑙e喅鍚屾闂銆?/p>

涓€.AQS鍩虹鍚屾鍣ㄥ熀鏈悊璁?/h2>

鍦↗ava棰嗗煙涓?鍚屾鍣ㄦ槸涓撻棬涓哄绾跨▼骞跺彂璁捐鐨勫悓姝ユ満鍒讹紝涓昏鏄绾跨▼骞跺彂鎵ц鏃剁嚎绋嬩箣闂撮€氳繃鏌愮鍏变韩鐘舵€佹潵瀹炵幇鍚屾锛屽彧鏈夊綋鐘舵€佹弧瓒宠繖绉嶆潯浠舵椂绾跨▼鎵嶅線涓嬫墽琛岀殑涓€绉嶅悓姝ユ満鍒躲€?/p>

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第6张

<br />涓€涓爣鍑嗙殑AQS鍚屾鍣ㄤ富瑕佹湁鍚屾鐘舵€佹満鍒讹紝绛夊緟闃熷垪锛屾潯浠堕槦鍒楋紝鐙崰妯″紡锛屽叡浜ā寮忕瓑浜斿ぇ鏍稿績瑕佺礌缁勬垚銆?lt;br />鍦↗ava棰嗗煙涓紝JDK鐨凧UC(java.util.concurrent.)鍖呬腑鎻愪緵浜嗗悇绉嶅苟鍙戝伐鍏凤紝浣嗘槸澶ч儴鍒嗗悓姝ュ伐鍏风殑瀹炵幇鍩轰簬AbstractQueuedSynchronizer绫诲疄鐜帮紝鍏跺唴閮ㄧ粨鏋勪富瑕佸涓嬶細

  • 鍚屾鐘舵€佹満鍒?Synchronization Status)锛氫富瑕佺敤浜庡疄鐜伴攣(Lock)鏈哄埗锛屾槸鎸囧悓姝ョ姸鎬侊紝鍏惰姹傚浜庣姸鎬佺殑鏇存柊蹇呴』鍘熷瓙鎬х殑
  • 绛夊緟闃熷垪(Wait Queue)锛氫富瑕佺敤浜庡瓨鏀剧瓑寰呯嚎绋嬭幏鍙栧埌鐨勯攣璧勬簮锛屽苟涓旀妸绾跨▼缁存姢鍒颁竴涓狽ode(鑺傜偣)閲岄潰鍜岀淮鎶や竴涓潪闃诲鐨凜HL Node FIFO(鍏堣繘鍏堝嚭)闃熷垪锛屼富瑕佹槸閲囩敤鑷棆閿?CAS鎿嶄綔鏉ヤ繚璇佽妭鐐规彃鍏ュ拰绉婚櫎鐨勫師瀛愭€ф搷浣溿€?/li>
  • 鏉′欢闃熷垪(Condition Queue)锛氱敤浜庡疄鐜伴攣鐨勬潯浠舵満鍒讹紝涓€鑸富瑕佹槸鎸囨浛鎹⑩€滅瓑寰?閫氱煡鈥濆伐浣滄満鍒讹紝涓昏鏄€氳繃ConditionObject瀵硅薄瀹炵幇Condition鎺ュ彛鎻愪緵鐨勬柟娉曞疄鐜般€?/li>
  • 鐙崰妯″紡(Exclusive Mode)锛氫富瑕佺敤浜庡疄鐜扮嫭鍗犻攣锛屼富瑕佹槸鍩轰簬闈欐€佸唴閮ㄧ被Node鐨勫父閲忔爣蹇桬XCLUSIVE鏉ユ爣璇嗚鑺傜偣鏄嫭鍗犳ā寮?/li>
  • 鍏变韩妯″紡(Shared Mode)锛氫富瑕佺敤浜庡疄鐜板叡浜攣锛屼富瑕佹槸鍩轰簬闈欐€佸唴閮ㄧ被Node鐨勫父閲忔爣蹇桽HARED鏉ユ爣璇嗚鑺傜偣鏄叡浜ā寮?/li>
鎴戜滑鍙互寰楀埌涓€涓瘮杈冮€氱敤鐨勫苟鍙戝悓姝ュ伐鍏峰熀纭€妯″瀷锛屽ぇ鑷村寘鍚涓嬪嚑涓唴瀹癸紝鍏朵腑锛?lt;br />
Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第7张
  • 鏉′欢鍙橀噺(Conditional Variable)锛?鍒╃敤绾跨▼闂村叡浜殑鍙橀噺杩涜鍚屾鐨勪竴绉嶅伐浣滄満鍒?/li>
  • 鍏变韩鍙橀噺((Shared Variable))锛氫竴鑸寚瀵硅薄瀹炰綋瀵硅薄鐨勬垚鍛樺彉閲忓拰灞炴€?/li>
  • 闃诲闃熷垪(Blocking Queue)锛氬叡浜彉閲?Shared Variable)鍙婂叾瀵瑰叡浜彉閲忕殑鎿嶄綔缁熶竴灏佽
  • 绛夊緟闃熷垪(Wait Queue)锛氭瘡涓潯浠跺彉閲忛兘瀵瑰簲鏈変竴涓瓑寰呴槦鍒?Wait Queue),鍐呴儴闇€瑕佸疄鐜板叆闃熸搷浣?Enqueue)鍜屽嚭闃熸搷浣?Dequeue)鏂规硶
  • 鍙橀噺鐘舵€佹弿杩版満(Synchronization Status)锛氭弿杩版潯浠跺彉閲忓拰鍏变韩鍙橀噺涔嬮棿鐘舵€佸彉鍖栵紝鍙堝彲浠ョО鍏朵负鍚屾鐘舵€?/li>
  • 宸ヤ綔妯″紡(Operation Mode)锛?绾跨▼璧勬簮鍏锋湁鎺掍粬鎬э紝鍥犳瀹氫箟鐙崰妯″紡鍜屽叡浜ā寮忎袱绉嶅伐浣滄ā寮?/li>

缁间笂鎵€杩帮紝鏉′欢鍙橀噺鍜岀瓑寰呴槦鍒楃殑浣滅敤鏄В鍐崇嚎绋嬩箣闂寸殑鍚屾闂锛涘叡浜彉閲忎笌闃诲闃熷垪鐨勪綔鐢ㄦ槸瑙e喅绾跨▼涔嬮棿鐨勪簰鏂ラ棶棰樸€?/p>

浜? JDK鏄惧紡閿佺粺涓€姒傚康妯″瀷

鍦ㄥ苟鍙戠紪绋嬮鍩燂紝鏈変袱澶ф牳蹇冮棶棰橈細涓€涓槸浜掓枼锛屽嵆鍚屼竴鏃跺埢鍙厑璁镐竴涓嚎绋嬭闂叡浜祫婧愶紱鍙︿竴涓槸鍚屾锛屽嵆绾跨▼涔嬮棿濡備綍閫氫俊銆佸崗浣溿€?/p>

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第8张

缁煎悎Java棰嗗煙涓殑骞跺彂閿佺殑鍚勭瀹炵幇涓庡簲鐢ㄥ垎鏋愭潵鐪嬶紝涓€鎶婇攣鎴栬€呬竴绉嶉攣锛屽熀鏈笂閮戒細鍖呭惈浠ヤ笅鍑犱釜鏂归潰锛?/p>

  • 閿佺殑鍚屾鍣ㄥ伐浣滄満鍒讹細涓昏鏄€冭檻鍏变韩妯″紡杩樻槸鐙韩妯″紡锛屾槸鍚︽敮鎸佽秴鏃舵満鍒讹紝浠ュ強鏄惁鏀寔瓒呮椂鏈哄埗锛?/li>
  • 閿佺殑鍚屾鍣ㄥ伐浣滄ā寮忥細涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄥ皝瑁呭唴閮ㄥ悓姝ュ櫒锛屾槸鍚﹁€冭檻鍏钩/闈炲叕骞虫ā寮忥紵
  • 閿佺殑鐘舵€佸彉閲忔満鍒讹細 涓昏閿佺殑鐘舵€佽缃紝鏄惁鍏变韩鐘舵€佸彉閲忥紵
  • 閿佺殑闃熷垪灏佽瀹氫箟锛氫富瑕佹槸鎸囩瓑寰呴槦鍒楀拰鏉′欢闃熷垪锛屾槸鍚﹂渶瑕佹潯浠堕槦鍒楁垨鑰呯瓑寰呴槦鍒楀畾涔夛紵
  • 閿佺殑搴曞眰瀹炵幇鎿嶄綔锛?涓昏鏄寚搴曞眰CL閿佸拰CAS鎿嶄綔锛屾槸鍚﹂渶瑕佽€冭檻鑷棆閿佹垨鑰匔AS鎿嶄綔瀹炰緥瀵硅薄鏂规硶锛?/li>
  • 閿佺殑缁勫悎瀹炵幇鏂伴攣锛?涓昏鏄熀浜庣嫭鍗犻攣鍜屽叡浜攣锛屾槸鍚﹁€冭檻瀵瑰簲API鑷畾涔夋搷浣滃疄鐜帮紵

缁间笂鎵€杩帮紝澶ц嚧鍙互鏍规嵁涓婅堪杩欎簺鏂瑰悜锛屾垜浠究鍙互娓呮馃墣锔忕煡閬揓ava棰嗗煙涓悇绉嶉攣瀹炵幇鐨勫熀鏈悊璁烘椂鍜屽疄鐜版€濇兂銆?/p>

浜?StampedLock(鍗版埑閿?鐨勮璁′笌瀹炵幇

鍦↗ava棰嗗煙涓紝StampedLock(鍗版埑閿?鏄拡瀵逛簬Java澶氱嚎绋嬪苟鍙戞帶鍒朵腑寮曞叆涓€涓叡浜攣瀹氫箟璇绘搷浣滀笌鐙崰閿佸畾涔夎鎿嶄綔绛夊満鏅叡鍚岀粍鍚堟瀯鎴愪竴鎶婇攣鏉ユ彁楂樺苟鍙戯紝涓昏鏄熀浜庤嚜瀹氫箟API鎿嶄綔瀹炵幇鐨勪竴绉嶅苟鍙戞帶鍒跺伐鍏风被銆?/p>

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第9张

1. 璁捐鎬濇兂

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第10张

<br />StampedLock锛堝嵃鎴抽攣锛夋槸瀵筊eentrantReadWriteLock璇诲啓閿佺殑涓€ 绉嶆敼杩涳紝涓昏鐨勬敼杩涗负锛氬湪娌℃湁鍐欏彧鏈夎鐨勫満鏅笅锛孲tampedLock鏀寔 涓嶇敤鍔犺閿佽€屾槸鐩存帴杩涜璇绘搷浣滐紝鏈€澶х▼搴︽彁鍗囪鐨勬晥鐜囷紝鍙湁鍦ㄥ彂 鐢熻繃鍐欐搷浣滀箣鍚庯紝鍐嶅姞璇婚攣鎵嶈兘杩涜璇绘搷浣溿€?lt;br />涓€鑸潵璇达紝StampedLock 閲岀殑鍐欓攣鍜屾偛瑙傝閿佸姞閿佹垚鍔熶箣鍚庯紝閮戒細杩斿洖涓€涓?stamp锛涚劧鍚庤В閿佺殑鏃跺€欙紝闇€瑕佷紶鍏ヨ繖涓?stamp銆?/p>

1.1 鍗版埑閿佺殑鍩烘湰鐞嗚

铏界劧鍩轰簬AQS鍩虹鍚屾鍣ㄥ疄鐜颁簡鍚勭閿侊紝浣嗘槸鐢变簬閲囩敤鐨勮嚜鏃嬮攣+CAS鎿嶄綔鏂瑰紡浼氬鑷村涓嬩袱涓棶棰橈細

  • CAS鎭舵€х┖鑷棆浼氭氮璐瑰ぇ閲忕殑CPU璧勬簮
  • 鍦⊿MP鏋舵瀯鐨凜PU涓婁細瀵艰嚧鈥滄€荤嚎椋庢毚鈥濋棶棰?/li>

瑙e喅CAS鎭舵€х┖鑷棆鐨勬湁鏁堟柟寮忎箣涓€鏄互绌洪棿鎹㈡椂闂达紝杈冧负甯歌鐨?鏂规鏈変袱绉嶏細鍒嗘暎鎿嶄綔鐑偣鍜屼娇鐢ㄩ槦鍒楀墛宄般€?lt;br />鍩轰簬杩欎釜鍩虹锛屽湪JDK1.8鐗堟湰涓紝鍩轰簬浣跨敤闃熷垪鍓婂嘲鐨勬柟寮忥紝鑷畾涔堿PI鎿嶄綔锛屾彁渚涗簡StampedLock(鍗版埑閿?鐨勫疄鐜般€?lt;br />绠€鍗曟潵璇达紝StampedLock(鍗版埑閿?鎻愪緵浜嗕笁绉嶉攣鐨勫疄鐜版ā寮忥紝鍏朵腑锛?/p>

  • 鎮茶璇婚攣锛氫笌ReadWriteLock鐨勮閿佺被浼硷紝澶氫釜绾跨▼鍙互鍚?鏃惰幏鍙栨偛瑙傝閿侊紝鎮茶璇婚攣鏄竴涓叡浜攣銆?/li>
  • 涔愯璇婚攣锛氱浉褰撲簬鐩存帴鎿嶄綔鏁版嵁锛屼笉鍔犱换浣曢攣锛岃繛璇婚攣閮戒笉 瑕併€?/li>
  • 鍐欓攣锛氫笌ReadWriteLock鐨勫啓閿佺被浼硷紝鍐欓攣鍜屾偛瑙傝閿佹槸浜?鏂ョ殑銆傝櫧鐒跺啓閿佷笌涔愯璇婚攣涓嶄細浜掓枼锛屼絾鏄湪鏁版嵁琚洿鏂颁箣鍚庯紝涔嬪墠 閫氳繃涔愯璇婚攣鑾峰緱鐨勬暟鎹凡缁忓彉鎴愪簡鑴忔暟鎹€?/li>

1.1 鍗版埑閿佺殑瀹炵幇鎬濇兂

StampedLock(鍗版埑閿?涓庡叾浠栨樉寮忛攣涓嶅悓鐨勬槸锛屼富瑕佹槸鏄渶鏃╁湪JDK1.8鐗堟湰涓彁渚涚殑锛屼粠璁捐鎬濇兂涓婃潵鐪嬶紝涓昏鍖呮嫭鍏变韩鐘舵€佸彉閲忔満鍒讹紝鍐呯疆鐨勭瓑寰呮暟鎹槦鍒楋紝璇婚攣瑙嗗浘锛屽啓閿佽鍥句互鍙婅鍐欓攣瑙嗗浘绛?涓牳蹇冭绱犮€傚叾涓細

  • 鍏变韩鐘舵€佸彉閲忔満鍒讹細涓昏鏄湪鍐呴儴灏佽涓€浜涢潤鎬佺鏈夌殑甯搁噺锛岀敤浜庢弿杩板悇涓ā寮忎箣闂寸殑鐘舵€佹弿杩扮瓑銆?/li>
  • 鍐呯疆鐨勭瓑寰呮暟鎹槦鍒楋細涓昏鏄嚜瀹氫箟瀹炵幇涓€涓熀浜嶤LH閿佺殑绛夊緟闃熷垪
  • 璇婚攣瑙嗗浘锛氬熀浜嶭ock鎺ュ彛瀹炵幇涓€涓搴旇閿佺殑瑙嗗浘
  • 鍐欓攣瑙嗗浘锛氬熀浜嶭ock鎺ュ彛瀹炵幇涓€涓搴斿啓閿佺殑瑙嗗浘
  • 璇诲啓閿佽鍥撅細鍩轰簬ReadWriteLock鎺ュ彛瀹炵幇涓€涓寘鍚閿佸拰鍐欓攣鐨勮鍥?/li>

2. 鍩烘湰瀹炵幇

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第11张

鍦⊿tampedLock(鍗版埑閿?绫荤殑JDK1.8鐗堟湰涓紝瀵逛簬StampedLock鐨勫熀鏈疄鐜板涓嬶細


/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    private static final long serialVersionUID = -6001602636862214147L;

    /** StampedLock閿?鑷棆鎺у埗鐨勬渶澶у厑璁告牳蹇冪嚎绋嬫暟 */
    private static final int NCPU = Runtime.getRuntime().availableProcessors();

    /** StampedLock閿?绛夊緟闃熷垪鑷棆鎺у埗鐨勬渶澶ц嚜鏃嬮槇鍊?*/
    private static final int SPINS = (NCPU > 1) 1 << 6 : 0;

    /** StampedLock閿?绛夊緟闃熷垪澶磋妭鐐硅嚜鏃嬫帶鍒剁殑鏈€澶ц嚜鏃嬮槇鍊?*/
    private static final int HEAD_SPINS = (NCPU > 1) 1 << 10 : 0;

    /** StampedLock閿?绛夊緟闃熷垪澶磋妭鐐硅嚜鏃嬫帶鍒剁殑鏈€澶ц嚜鏃嬮槇鍊?*/
    private static final int MAX_HEAD_SPINS = (NCPU > 1) 1 << 16 : 0;

    /** StampedLock閿?杩涘叆闃诲涔嬪墠鐨勬渶澶ч噸璇曟鏁?*/
    private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1

    //... 鍏朵粬閿佽祫婧愮殑鐘舵€佸父閲?

    /** StampedLock閿?CLH闃熷垪鐨勫ご閮?head)鑺傜偣 */
    private transient volatile WNode whead;

    /** StampedLock閿?CLH闃熷垪鐨勫熬閮?tail)鑺傜偣 */
    private transient volatile WNode wtail;

    /** StampedLock閿?璇婚攣瑙嗗浘*/
    transient ReadLockView readLockView;

    /** StampedLock閿?鍐欓攣瑙嗗浘*/
    transient WriteLockView writeLockView;

    /** StampedLock閿?璇诲啓閿佽鍥?*/
    transient ReadWriteLockView readWriteLockView;


    /** StampedLock閿?閿佺殑鏈€鍘熷鐨勭姸鎬佸垵濮嬪€?*/
    private static final long ORIGIN = WBIT << 1;

    /** StampedLock閿?鍚勭閿佺殑鍚屾鐘舵€佸彉閲?*/
    private transient volatile long state;

    /** StampedLock閿?璇婚攣鐨勬孩鍑虹殑鎷撳睍鏍囪 */
    private transient int readerOverflow;

    /** StampedLock閿?鏋勯€犳柟娉?*/
    public StampedLock() {
        state = ORIGIN;
    }

    /** StampedLock閿?瀹炰緥鍖朢eadLock鏂规硶 */
    public Lock asReadLock() {
        ReadLockView v;
        return ((v = readLockView) != null v :
                (readLockView = new ReadLockView()));
    }

    /** StampedLock閿?瀹炰緥鍖朩riteLock鏂规硶 */
    public Lock asWriteLock() {
        WriteLockView v;
        return ((v = writeLockView) != null v :
                (writeLockView = new WriteLockView()));
    }

    /** StampedLock閿?瀹炰緥鍖朢eadWriteLock鏂规硶 */
    public ReadWriteLock asReadWriteLock() {
        ReadWriteLockView v;
        return ((v = readWriteLockView) != null v :
                (readWriteLockView = new ReadWriteLockView()));
    }

    /** StampedLock閿?鑾峰彇ReadLock鏂规硶 */
    public long readLock() {
        long s = state, next;  // bypass acquireRead on common uncontended case
        return ((whead == wtail && (s & ABITS) < RFULL &&
                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
                next : acquireRead(false, 0L));
    }

    /** StampedLock閿?鑾峰彇WriteLock鏂规硶 */
    public long writeLock() {
        long s, next;  // bypass acquireWrite in fully unlocked case only
        return ((((s = state) & ABITS) == 0L &&
                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
                next : acquireWrite(false, 0L));
    }

    //... 鍏朵粬浠g爜
}

2.1 鍏变韩鐘舵€佸彉閲忔満鍒?/h4>
/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?鑷棆鎺у埗鐨勬渶澶у厑璁告牳蹇冪嚎绋嬫暟 */
    private static final int NCPU = Runtime.getRuntime().availableProcessors();

    /** StampedLock閿?绛夊緟闃熷垪鑷棆鎺у埗鐨勬渶澶ц嚜鏃嬮槇鍊?*/
    private static final int SPINS = (NCPU > 1) 1 << 6 : 0;

    /** StampedLock閿?绛夊緟闃熷垪澶磋妭鐐硅嚜鏃嬫帶鍒剁殑鏈€澶ц嚜鏃嬮槇鍊?*/
    private static final int HEAD_SPINS = (NCPU > 1) 1 << 10 : 0;

    /** StampedLock閿?绛夊緟闃熷垪澶磋妭鐐硅嚜鏃嬫帶鍒剁殑鏈€澶ц嚜鏃嬮槇鍊?*/
    private static final int MAX_HEAD_SPINS = (NCPU > 1) 1 << 16 : 0;

    /** StampedLock閿?杩涘叆闃诲涔嬪墠鐨勬渶澶ч噸璇曟鏁?*/
    private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1

    // Values for lock state and stamp operations
    /** StampedLock閿?璇婚攣绉诲姩鐨勪綅鏁?*/
    private static final long RUNIT = 1L;

    /** StampedLock閿?鍐欓攣绉诲姩鐨勪綅鏁?*/
    private static final long WBIT  = 1L << LG_READERS;

    /** StampedLock閿?璇婚攣绉诲姩鐨勪綅鏁?*/
    private static final long RBITS = WBIT - 1L;

    /** StampedLock閿?璇婚攣绉诲姩鐨勪綅鏁?*/
    private static final long RFULL = RBITS - 1L;

    /** StampedLock閿?璇诲啓閿佺Щ鍔ㄧ殑浣嶆暟 */
    private static final long ABITS = RBITS | WBIT;

    /** StampedLock閿?璇诲啓閿佺Щ鍔ㄧ殑浣嶆暟 */
    private static final long SBITS = ~RBITS; 

    // Special value from cancelled acquire methods so caller can throw IE
    /** StampedLock閿?绾跨▼瀵硅薄涓柇鏍囪瘑 */
    private static final long INTERRUPTED = 1L;

    // Values for node status; order matters
    /** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
    private static final int WAITING   = -1;

    /** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
    private static final int CANCELLED =  1;

    // Modes for nodes (int not boolean to allow arithmetic)
    /** StampedLock閿?鐢ㄤ簬琛ㄧず鍦ㄩ槦鍒椾箣涓槸璇绘ā寮?*/
    private static final int RMODE = 0;

    /** StampedLock閿?鐢ㄤ簬琛ㄧず鍦ㄩ槦鍒椾箣涓槸鍐欐ā寮?*/
    private static final int WMODE = 1;

    //... 鍏朵粬浠g爜

    // Unsafe mechanics

    /** StampedLock閿?瀹炰緥鍖朥nsafe瀵硅薄 */
    private static final sun.misc.Unsafe U;

    /** StampedLock閿?鐘舵€?*/
    private static final long STATE;

    /** StampedLock閿?澶撮儴鑺傜偣 */
    private static final long WHEAD;

    /** StampedLock閿?灏鹃儴鑺傜偣 */
    private static final long WTAIL;

    /** StampedLock閿?鍚庣户鑺傜偣 */
    private static final long WNEXT;

    /** StampedLock閿?鑺傜偣鐘舵€?*/
    private static final long WSTATUS;

    /** StampedLock閿?鑺傜偣閾捐〃 */
    private static final long WCOWAIT;

    /** StampedLock閿?涓柇鏍囪瘑 */
    private static final long PARKBLOCKER;

    static {
        try {
            U = sun.misc.Unsafe.getUnsafe();
            Class<?> k = StampedLock.class;
            Class<?> wk = WNode.class;
            STATE = U.objectFieldOffset
                (k.getDeclaredField("state"));
            WHEAD = U.objectFieldOffset
                (k.getDeclaredField("whead"));
            WTAIL = U.objectFieldOffset
                (k.getDeclaredField("wtail"));
            WSTATUS = U.objectFieldOffset
                (wk.getDeclaredField("status"));
            WNEXT = U.objectFieldOffset
                (wk.getDeclaredField("next"));
            WCOWAIT = U.objectFieldOffset
                (wk.getDeclaredField("cowait"));
            Class<?> tk = Thread.class;
            PARKBLOCKER = U.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));

        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

瀵逛簬StampedLock閿佷腑瀵逛簬鍚勭璧勬簮鐨勬爣璁帮紝鍏跺皝瑁呬簡涓€绯诲垪鐨勫父閲忥紝涓昏鍙互鍒嗕负浠ヤ笅鍑犱釜鏂归潰锛屽叾涓細

  • 鏍稿績璧勬簮甯搁噺鏍囪瘑锛氭槸瀵圭嚎绋嬫搷浣滆祫婧愮殑鎻愪緵鐨勫父閲忓皝瑁咃紝鍏朵腑锛?
    • NCPU锛氳嚜鏃嬫帶鍒剁殑鏍稿績绾跨▼鏁伴噺锛屼富瑕侀€氳繃Runtime.getRuntime().availableProcessors()鑾峰彇璁剧疆銆?/li>
    • SPINS锛氱瓑寰呴槦鍒楄嚜鏃嬫帶鍒剁殑鏈€澶ц嚜鏃嬮槇鍊硷紝涓昏閫氳繃 (_NCPU _> 1) 1 << 6 : 0鑾峰彇璁剧疆
    • HEAD_SPINS锛?绛夊緟闃熷垪澶磋妭鐐硅嚜鏃嬫帶鍒剁殑鑷棆闃堝€硷紝涓昏閫氳繃 (_NCPU _> 1) 1 << 10 : 0鑾峰彇璁剧疆
    • MAX_HEAD_SPINS锛氱瓑寰呴槦鍒楀ご鑺傜偣鑷棆鎺у埗鐨勬渶澶ц嚜鏃嬮槇鍊硷紝涓昏閫氳繃(_NCPU _> 1) 1 << 16 : 0鑾峰彇璁剧疆
    • OVERFLOW_YIELD_RATE锛氱嚎绋嬭姝ユ搷浣滅瓑寰呯殑鑷棆闃堝€硷紝榛樿鍊间负7
    • LG_READERS锛氳閿佹孩鍑虹殑鏈€澶ч槇鍊硷紝榛樿鍊间负7
    • INTERRUPTED锛氱嚎绋嬩腑鏂爣璇嗭紝榛樿鍊间负1L
  • 閿佺姸鎬佸€艰缃爣璇嗭細
    • ORIGIN锛氶攣鐘舵€佺殑鍒濆鍊硷紝榛樿鍊间负WBIT << 1锛屽鏋滃垎閰嶅け璐ラ粯璁よ缃负0
  • 閿佺姸鎬佺殑鎿嶄綔鏍囪瘑锛?
    • RUNIT锛氳閿佺Щ鍔ㄧ殑浣嶆暟锛岄粯璁ゅ€间负 1
    • WBIT锛氬啓閿佺Щ鍔ㄧ殑浣嶆暟锛岄粯璁ゅ€间负1L << LG_READERS
    • RBITS锛氳閿佺Щ鍔ㄧ殑浣嶆暟锛?/em>榛樿鍊间负_WBIT _- 1L
    • RFULL锛氱Щ鍔ㄧ殑浣嶆暟锛岄粯璁ゅ€间负_RBITS _- 1L
    • ABITS锛氶攣绉诲姩鐨勪綅鏁帮紝榛樿鍊间负 _RBITS _| WBIT
    • SBITS锛氶攣绉诲姩鐨勪綅鏁帮紝榛樿鍊间负 ~RBITS
  • 绛夊緟闃熷垪鑺傜偣鏍囪瘑锛?
    • WAITING锛氱瓑寰呯姸鎬佺殑鍒濆鍊硷紝榛樿鍊间负-1
    • CANCELLED锛氬彇娑堢姸鎬佺殑鍒濆鍊硷紝榛樿鍊间负1
  • 璇诲啓閿佺殑妯″紡鏍囪瘑锛?
    • RMODE锛氳閿佹ā寮忥紝榛樿鍊间负0
    • WMODE锛氬啓閿佹ā寮忥紝榛樿鍊间负1
  • CAS鎿嶄綔鐘舵€佹爣璇嗭細灏佽浜咰AS鎿嶄綔鐘舵€佹爣璇嗭紝杩橀€氳繃鍙嶅皠瀹炰緥鍖栦簡Unsafe瀵硅薄瀹炰緥銆?/li>

2.2 鍐呯疆鐨勭瓑寰呴槦鍒梂Node

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** Wait nodes */
    static final class WNode {
        /** StampedLock閿?闃熷垪鍓嶉┍鑺傜偣 */
        volatile WNode prev;
        /** StampedLock閿?闃熷垪鍚庨┍鑺傜偣 */
        volatile WNode next;
        /** StampedLock閿?閿佺殑瀛樺偍鍒楄〃 */
        volatile WNode cowait;    // list of linked readers
        /** StampedLock閿?绾跨▼瀵硅薄 */
        volatile Thread thread;   // non-null while possibly parked
        /** StampedLock閿?閿佺殑鐘舵€?*/
        volatile int status;      // 0, WAITING, or CANCELLED
        /** StampedLock閿?閿佺殑妯″紡 */
        final int mode;           // RMODE or WMODE

        WNode(int m, WNode p) { mode = m; prev = p; }
    }

    /** Head of CLH queue */
    /** StampedLock閿?澶撮儴鑺傜偣 */
    private transient volatile WNode whead;

    /** Tail (last) of CLH queue */
    /** StampedLock閿?灏鹃儴鑺傜偣 */
    private transient volatile WNode wtail;

}

瀵逛簬StampedLock閿佸浜庣瓑寰呴槦鍒楃殑瀹炵幇锛屼富瑕佸寘鍚互涓嬪嚑涓柟闈㈢殑鍐呭锛屽叾涓細<br />


Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第12张
  • 灏佽浜嗕竴涓瓑寰呴槦鍒梂Node鐨勯潤鎬佸唴閮ㄧ被锛屽叾涓細
    • prev锛氱瓑寰呴槦鍒楃殑鍓嶉┍鑺傜偣
    • next锛氱瓑寰呴槦鍒楃殑鍚庨┍鑺傜偣
    • cowait锛氳〃绀轰緷鎹攣鏍囪瀛樺偍褰撳墠绾跨▼鍏ラ槦鐨勬儏鍐碉紝闃熷垪閿佸垪琛?/li>
    • thread锛?绾跨▼瀵硅薄锛屼竴鑸兘鏄綋鍓嶈幏鍙栭攣鐨勭嚎绋?/li>
    • status锛氱敤浜庤〃绀洪攣鐨勭姸鎬佸彉閲忥紝瀵瑰簲鐫€甯搁噺0锛學AITING(-1), CANCELLED(1)锛屽叾涓紝0琛ㄧず姝e父鐘舵€侊紝WAITING(-1)涓虹瓑寰呯姸鎬侊紝CANCELLED(1)涓哄彇娑堢姸鎬併€?/li>
    • mode锛氱敤浜庤〃绀洪攣鐨勬ā寮忥紝瀵瑰簲鐫€甯搁噺RMODE鍜學MODE锛屽叾涓璕MODE涓哄啓妯″紡锛學MOD涓鸿妯″紡
    • 鏋勯€犳柟娉昗Node(int m, WNode p)锛氱敤浜庡疄渚嬪寲WNode瀵硅薄锛屽疄鐜颁竴涓瓑寰呴槦鍒?/li>
  • 瀹炰緥鍖栫瓑寰呴槦鍒楀璞★紝涓昏灏佽涓€涓ご閮ㄨ妭鐐箇head鍜屽熬閮ㄨ妭鐐箇tail鐨勫璞?/li>

2.3 鍏辩敤鐨勮閿佹牳蹇冨鐞嗛€昏緫

棣栧厛锛屽浜嶴tampedLock閿佺殑璇婚攣瑙嗗浘涓庡啓閿佽鍥剧殑闃熷垪鎿嶄綔锛屾湁涓€涓牳蹇冪殑澶勭悊閫昏緫锛?/p>

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

      /** StampedLock閿?鍙栨秷鍏ラ槦鍒?*/
      private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
        if (node != null && group != null) {
            Thread w;
            node.status = CANCELLED;
            // unsplice cancelled nodes from group
            for (WNode p = group, q; (q = p.cowait) != null;) {
                if (q.status == CANCELLED) {
                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
                    p = group; // restart
                }
                else
                    p = q;
            }
            if (group == node) {
                for (WNode r = group.cowait; r != null; r = r.cowait) {
                    if ((w = r.thread) != null)
                        U.unpark(w);       // wake up uncancelled co-waiters
                }
                for (WNode pred = node.prev; pred != null; ) { // unsplice
                    WNode succ, pp;        // find valid successor
                    while ((succ = node.next) == null ||
                           succ.status == CANCELLED) {
                        WNode q = null;    // find successor the slow way
                        for (WNode t = wtail; t != null && t != node; t = t.prev)
                            if (t.status != CANCELLED)
                                q = t;     // don't link if succ cancelled
                        if (succ == q ||   // ensure accurate successor
                            U.compareAndSwapObject(node, WNEXT,
                                                   succ, succ = q)) {
                            if (succ == null && node == wtail)
                                U.compareAndSwapObject(this, WTAIL, node, pred);
                            break;
                        }
                    }
                    if (pred.next == node) // unsplice pred link
                        U.compareAndSwapObject(pred, WNEXT, node, succ);
                    if (succ != null && (w = succ.thread) != null) {
                        succ.thread = null;
                        U.unpark(w);       // wake up succ to observe new pred
                    }
                    if (pred.status != CANCELLED || (pp = pred.prev) == null)
                        break;
                    node.prev = pp;        // repeat if new pred wrong/cancelled
                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
                    pred = pp;
                }
            }
        }
        WNode h; // Possibly release first waiter
        while ((h = whead) != null) {
            long s; WNode q; // similar to release() but check eligibility
            if ((q = h.next) == null || q.status == CANCELLED) {
                for (WNode t = wtail; t != null && t != h; t = t.prev)
                    if (t.status <= 0)
                        q = t;
            }
            if (h == whead) {
                if (q != null && h.status == 0 &&
                    ((s = state) & ABITS) != WBIT && // waiter is eligible
                    (s == 0L || q.mode == RMODE))
                    release(h);
                break;
            }
        }
        return (interrupted || Thread.interrupted()) INTERRUPTED : 0L;
    }
}

鍏舵锛屽浜嶴tampedLock閿佺殑璇婚攣瑙嗗浘鐨勫疄鐜颁綔鏉ョ湅锛屼富瑕佹牳蹇冨鐞嗗涓嬶細

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?鑾峰彇璇婚攣 */
    private long acquireRead(boolean interruptible, long deadline) {
        WNode node = null, p;
        for (int spins = -1;;) {
            WNode h;
            if ((h = whead) == (p = wtail)) {
                for (long m, s, ns;;) {
                    if ((m = (s = state) & ABITS) < RFULL ?
                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
                        return ns;
                    else if (m >= WBIT) {
                        if (spins > 0) {
                            if (LockSupport.nextSecondarySeed() >= 0)
                                --spins;
                        }
                        else {
                            if (spins == 0) {
                                WNode nh = whead, np = wtail;
                                if ((nh == h && np == p) || (h = nh) != (p = np))
                                    break;
                            }
                            spins = SPINS;
                        }
                    }
                }
            }
            if (p == null) { // initialize queue
                WNode hd = new WNode(WMODE, null);
                if (U.compareAndSwapObject(this, WHEAD, null, hd))
                    wtail = hd;
            }
            else if (node == null)
                node = new WNode(RMODE, p);
            else if (h == p || p.mode != RMODE) {
                if (node.prev != p)
                    node.prev = p;
                else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
                    p.next = node;
                    break;
                }
            }
            else if (!U.compareAndSwapObject(p, WCOWAIT,
                                             node.cowait = p.cowait, node))
                node.cowait = null;
            else {
                for (;;) {
                    WNode pp, c; Thread w;
                    if ((h = whead) != null && (c = h.cowait) != null &&
                        U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
                        (w = c.thread) != null) // help release
                        U.unpark(w);
                    if (h == (pp = p.prev) || h == p || pp == null) {
                        long m, s, ns;
                        do {
                            if ((m = (s = state) & ABITS) < RFULL ?
                                U.compareAndSwapLong(this, STATE, s,
                                                     ns = s + RUNIT) :
                                (m < WBIT &&
                                 (ns = tryIncReaderOverflow(s)) != 0L))
                                return ns;
                        } while (m < WBIT);
                    }
                    if (whead == h && p.prev == pp) {
                        long time;
                        if (pp == null || h == p || p.status > 0) {
                            node = null; // throw away
                            break;
                        }
                        if (deadline == 0L)
                            time = 0L;
                        else if ((time = deadline - System.nanoTime()) <= 0L)
                            return cancelWaiter(node, p, false);
                        Thread wt = Thread.currentThread();
                        U.putObject(wt, PARKBLOCKER, this);
                        node.thread = wt;
                        if ((h != pp || (state & ABITS) == WBIT) &&
                            whead == h && p.prev == pp)
                            U.park(false, time);
                        node.thread = null;
                        U.putObject(wt, PARKBLOCKER, null);
                        if (interruptible && Thread.interrupted())
                            return cancelWaiter(node, p, true);
                    }
                }
            }
        }

        for (int spins = -1;;) {
            WNode h, np, pp; int ps;
            if ((h = whead) == p) {
                if (spins < 0)
                    spins = HEAD_SPINS;
                else if (spins < MAX_HEAD_SPINS)
                    spins <<= 1;
                for (int k = spins;;) { // spin at head
                    long m, s, ns;
                    if ((m = (s = state) & ABITS) < RFULL ?
                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                        WNode c; Thread w;
                        whead = node;
                        node.prev = null;
                        while ((c = node.cowait) != null) {
                            if (U.compareAndSwapObject(node, WCOWAIT,
                                                       c, c.cowait) &&
                                (w = c.thread) != null)
                                U.unpark(w);
                        }
                        return ns;
                    }
                    else if (m >= WBIT &&
                             LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
                        break;
                }
            }
            else if (h != null) {
                WNode c; Thread w;
                while ((c = h.cowait) != null) {
                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
                        (w = c.thread) != null)
                        U.unpark(w);
                }
            }
            if (whead == h) {
                if ((np = node.prev) != p) {
                    if (np != null)
                        (p = np).next = node;   // stale
                }
                else if ((ps = p.status) == 0)
                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
                else if (ps == CANCELLED) {
                    if ((pp = p.prev) != null) {
                        node.prev = pp;
                        pp.next = node;
                    }
                }
                else {
                    long time;
                    if (deadline == 0L)
                        time = 0L;
                    else if ((time = deadline - System.nanoTime()) <= 0L)
                        return cancelWaiter(node, node, false);
                    Thread wt = Thread.currentThread();
                    U.putObject(wt, PARKBLOCKER, this);
                    node.thread = wt;
                    if (p.status < 0 &&
                        (p != h || (state & ABITS) == WBIT) &&
                        whead == h && node.prev == p)
                        U.park(false, time);
                    node.thread = null;
                    U.putObject(wt, PARKBLOCKER, null);
                    if (interruptible && Thread.interrupted())
                        return cancelWaiter(node, node, true);
                }
            }
        }
    }
}

鐒跺悗锛屽浜嶴tampedLock閿佺殑鍐欓攣瑙嗗浘鐨勫疄鐜颁綔鏉ョ湅锛屼富瑕佹牳蹇冨鐞嗗涓嬶細

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?鑾峰彇鍐欓攣 */
    private long acquireWrite(boolean interruptible, long deadline) {
        WNode node = null, p;
        for (int spins = -1;;) { // spin while enqueuing
            long m, s, ns;
            if ((m = (s = state) & ABITS) == 0L) {
                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
                    return ns;
            }
            else if (spins < 0)
                spins = (m == WBIT && wtail == whead) SPINS : 0;
            else if (spins > 0) {
                if (LockSupport.nextSecondarySeed() >= 0)
                    --spins;
            }
            else if ((p = wtail) == null) { // initialize queue
                WNode hd = new WNode(WMODE, null);
                if (U.compareAndSwapObject(this, WHEAD, null, hd))
                    wtail = hd;
            }
            else if (node == null)
                node = new WNode(WMODE, p);
            else if (node.prev != p)
                node.prev = p;
            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
                p.next = node;
                break;
            }
        }

        for (int spins = -1;;) {
            WNode h, np, pp; int ps;
            if ((h = whead) == p) {
                if (spins < 0)
                    spins = HEAD_SPINS;
                else if (spins < MAX_HEAD_SPINS)
                    spins <<= 1;
                for (int k = spins;;) { // spin at head
                    long s, ns;
                    if (((s = state) & ABITS) == 0L) {
                        if (U.compareAndSwapLong(this, STATE, s,
                                                 ns = s + WBIT)) {
                            whead = node;
                            node.prev = null;
                            return ns;
                        }
                    }
                    else if (LockSupport.nextSecondarySeed() >= 0 &&
                             --k <= 0)
                        break;
                }
            }
            else if (h != null) { // help release stale waiters
                WNode c; Thread w;
                while ((c = h.cowait) != null) {
                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
                        (w = c.thread) != null)
                        U.unpark(w);
                }
            }
            if (whead == h) {
                if ((np = node.prev) != p) {
                    if (np != null)
                        (p = np).next = node;   // stale
                }
                else if ((ps = p.status) == 0)
                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
                else if (ps == CANCELLED) {
                    if ((pp = p.prev) != null) {
                        node.prev = pp;
                        pp.next = node;
                    }
                }
                else {
                    long time; // 0 argument to park means no timeout
                    if (deadline == 0L)
                        time = 0L;
                    else if ((time = deadline - System.nanoTime()) <= 0L)
                        return cancelWaiter(node, node, false);
                    Thread wt = Thread.currentThread();
                    U.putObject(wt, PARKBLOCKER, this);
                    node.thread = wt;
                    if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
                        whead == h && node.prev == p)
                        U.park(false, time);  // emulate LockSupport.park
                    node.thread = null;
                    U.putObject(wt, PARKBLOCKER, null);
                    if (interruptible && Thread.interrupted())
                        return cancelWaiter(node, node, true);
                }
            }
        }
    }
}

鏈€鍚庯紝缁煎悎瀵逛簬StampedLock閿佺殑璇婚攣鍜屽啓閿佺殑鑾峰彇鍜岄噴鏀剧瓑鎿嶄綔鏉ョ湅锛屼富瑕佹牳蹇冨鐞嗛兘浼氳皟鐢ㄤ互涓?涓柟娉曪紝鍏朵腑锛?/p>

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?璇婚攣婧㈠嚭閫掑澶勭悊鏂规硶 */
    private long tryIncReaderOverflow(long s) {
        // assert (s & ABITS) >= RFULL;
        if ((s & ABITS) == RFULL) {
            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
                ++readerOverflow;
                state = s;
                return s;
            }
        }
        else if ((LockSupport.nextSecondarySeed() &
                  OVERFLOW_YIELD_RATE) == 0)
            Thread.yield();
        return 0L;
    }

    /** StampedLock閿?璇婚攣婧㈠嚭閫掑噺澶勭悊鏂规硶 */
    private long tryDecReaderOverflow(long s) {
        // assert (s & ABITS) >= RFULL;
        if ((s & ABITS) == RFULL) {
            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
                int r; long next;
                if ((r = readerOverflow) > 0) {
                    readerOverflow = r - 1;
                    next = s;
                }
                else
                    next = s - RUNIT;
                state = next;
                return next;
            }
        }
        else if ((LockSupport.nextSecondarySeed() &
                  OVERFLOW_YIELD_RATE) == 0)
            Thread.yield();
        return 0L;
    }

}

  • tryIncReaderOverflow()鏂规硶锛氫富瑕佹槸瀹炵幇瀵逛簬閿佽幏鍙栬嚜鏃嬫椂鏈€澶ч噸璇曟鏁扮殑閫掑杩愮畻銆傚叾涓細
    • 瀵逛簬婊¤冻stamp >= RFULL鏉′欢鏃讹紝鍒╃敤compareAndSwapLong()鏂规硶鏉ュ疄鐜癈AS鎿嶄綔鍔犳寔淇敼鐘舵€佸€笺€傚浜巖eaderOverflow浣滆嚜澧炶繍绠楀悗杩斿洖涓€涓?em>stamp锛屽彲鑳藉瓨鍦ㄦ洿鏂板拰閲婃斁鎿嶄綔銆?/em>
    • 鍚﹀垯锛屽埄鐢↙ockSupport.nextSecondarySeed() 鍒ゆ柇锛屽浜庣嚎绋嬪仛璁╂澶勭悊锛岄粯璁よ繑鍥?
  • tryDecReaderOverflow()鏂规硶锛氫富瑕佹槸瀹炵幇瀵逛簬閿佽幏鍙栬嚜鏃嬫椂鏈€澶ч噸璇曟鏁扮殑閫掑噺杩愮畻銆傚叾涓細
    • 瀵逛簬婊¤冻stamp == RFULL鏉′欢鏃讹紝鍒╃敤compareAndSwapLong()鏂规硶鏉ュ疄鐜癈AS鎿嶄綔鍔犳寔淇敼鐘舵€佸€笺€傚浜巖eaderOverflow>0鍋氶€掑噺杩愮畻鍚庤繑鍥炰竴涓?em>stamp锛屽彲鑳藉瓨鍦ㄦ洿鏂板拰閲婃斁鎿嶄綔銆?/em>
    • 鍚﹀垯锛屽埄鐢↙ockSupport.nextSecondarySeed() 鍒ゆ柇锛屽浜庣嚎绋嬪仛璁╂澶勭悊锛岄粯璁よ繑鍥?

2.4 鍩轰簬Lock鎺ュ彛瀹炵幇鐨凴eadLockView

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?ReadLockView */
    final class ReadLockView implements Lock {

        /** StampedLock閿?鑾峰彇閿?*/
        public void lock() { readLock(); }

        /** StampedLock閿?鑾峰彇鍙腑鏂攣 */
        public void lockInterruptibly() throws InterruptedException {
            readLockInterruptibly();
        }

        /** StampedLock閿?灏濊瘯鑾峰彇閿?*/
        public boolean tryLock() { return tryReadLock() != 0L; }

        /** StampedLock閿?灏濊瘯鑾峰彇鍙秴鏃堕攣 */
        public boolean tryLock(long time, TimeUnit unit)
        throws InterruptedException {
            return tryReadLock(time, unit) != 0L;
        }
        /** StampedLock閿?閲婃斁 */
        public void unlock() { unstampedUnlockRead(); }

        /** StampedLock閿?涓嶆敮鎸佹潯浠跺彉閲忓畾涔?*/
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }
    }

    /** StampedLock閿?瀹炰緥鍖朢eadLock鏂规硶 */
    public Lock asReadLock() {
        ReadLockView v;
        return ((v = readLockView) != null v :
                (readLockView = new ReadLockView()));
    }

    /** StampedLock閿?瀹炰緥鍖朢eadLock鏂规硶 */
    public long readLock() {
        long s = state, next;  // bypass acquireRead on common uncontended case
        return ((whead == wtail && (s & ABITS) < RFULL &&
                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
                next : acquireRead(false, 0L));
    }

    /** StampedLock閿?瀹炰緥鍖朢eadLock鏂规硶 */
    public long tryReadLock() {
        for (;;) {
            long s, m, next;
            if ((m = (s = state) & ABITS) == WBIT)
                return 0L;
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                    return next;
            }
            else if ((next = tryIncReaderOverflow(s)) != 0L)
                return next;
        }
    }

    /** StampedLock閿?瀹炰緥鍖朢eadLock鏂规硶 */
    public long tryReadLock(long time, TimeUnit unit)
    throws InterruptedException {
        long s, m, next, deadline;
        long nanos = unit.toNanos(time);
        if (!Thread.interrupted()) {
            if ((m = (s = state) & ABITS) != WBIT) {
                if (m < RFULL) {
                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                        return next;
                }
                else if ((next = tryIncReaderOverflow(s)) != 0L)
                    return next;
            }
            if (nanos <= 0L)
                return 0L;
            if ((deadline = System.nanoTime() + nanos) == 0L)
                deadline = 1L;
            if ((next = acquireRead(true, deadline)) != INTERRUPTED)
                return next;
        }
        throw new InterruptedException();
    }

    /** StampedLock閿?閲婃斁閿佹柟娉?*/
    final void unstampedUnlockRead() {

        // 鑷棆鎿嶄綔
        for (;;) {
            long s, m; WNode h;
            if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
                throw new IllegalMonitorStateException();
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    break;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                break;
        }
    }



}

瀵逛簬ReadLock鐨勫疄鐜帮紝涓昏鍖呭惈浠ヤ笅鍑犱釜鏂归潰鐨勫唴瀹癸紝鍏朵腑锛?/p>

  • 鍩烘湰瀹炵幇鏂瑰紡锛氬熀浜嶭ock鎺ュ彛瀹炵幇锛屾彁渚涗簡瀵瑰簲鐨勯攣鑾峰彇鍜岄噴鏀炬搷浣滄柟娉曪紝鍏朵腑锛?
    • lock()鏂规硶锛氫竴鑸ā寮忥紝涓昏閫氳繃StampedLock绫讳腑readLock()鏂规硶瀹炵幇
    • lockInterruptibly()鏂规硶锛氬彲涓柇妯″紡锛屼富瑕侀€氳繃StampedLock绫讳腑readLockInterruptibly()鏂规硶瀹炵幇
    • 鏃犲弬鏁皌ryLock() 鏂规硶锛氬皾璇曡幏鍙栭攣锛屼富瑕佷緷鎹甋tampedLock绫讳腑tryReadLock() != 0L鏉ュ疄鐜?/li>
    • 鏈夊弬鏁皌ryLock() 鏂规硶锛氬皾璇曡幏鍙栭攣锛屼富瑕佷緷鎹甋tampedLock绫讳腑tryReadLock(long time, TimeUnit unit)!= 0L鏉ュ疄鐜?/li>
    • unlock()鏂规硶锛氶攣鐨勯噴鏀撅紝涓昏閫氳繃StampedLock绫讳腑unstampedUnlockRead()鏂规硶瀹炵幇
    • newCondition() 鏂规硶锛氫笉鏀寔鏉′欢鍙橀噺鐨勫畾涔夛紝榛樿璁剧疆鎶涘嚭UnsupportedOperationException
  • 瀵瑰簲澶勭悊鏂规硶锛氫富瑕佹槸鍦⊿tampedLock澶栧眰瀹炵幇鐨勬搷浣滄柟娉曪紝鍏朵腑锛?
    • readLock()鏂规硶锛氳閿佺殑瀹炵幇锛屼富瑕佹牳蹇冮€昏緫鍦╝cquireRead()鏂规硶
    • tryReadLock()鏂规硶锛氬皾璇曡幏鍙栬閿侊紝鏍稿績澶勭悊閫昏緫鏄牴鎹搴旂殑鏉′欢杩斿洖瀵瑰簲鐨勯攣鐨刜stamp锛屽惁鍒欐姏鍑篲InterruptedException銆?/li>
    • readLockInterruptibly()鏂规硶锛氳閿佺殑鍙腑鏂満鍒跺疄鐜帮紝鏍稿績澶勭悊閫昏緫鏄垽鏂嚎绋嬫槸鍚︿腑鏂互鍙婂埄鐢╝cquireRead鏂规硶楠岃瘉锛屾潯浠舵垚绔嬫椂锛岃繑鍥為攣鐨刜stamp锛屽惁鍒欐姏鍑篲InterruptedException銆?/li>
    • unstampedUnlockRead()鏂规硶锛氶噴鏀鹃攣锛屾牳蹇冨鐞嗛€昏緫鑷棆鎿嶄綔+compareAndSwapLong瀹炵幇銆?/li>

2.5 鍩轰簬Lock鎺ュ彛瀹炵幇鐨刉riteLockView

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    final class WriteLockView implements Lock {
        
        public void lock() { writeLock(); }
        
        public void lockInterruptibly() throws InterruptedException {
            writeLockInterruptibly();
        }
        
        public boolean tryLock() { return tryWriteLock() != 0L; }
        
        public boolean tryLock(long time, TimeUnit unit)
            throws InterruptedException {
            return tryWriteLock(time, unit) != 0L;
        }
        public void unlock() { unstampedUnlockWrite(); }
        
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }
    }



    /** StampedLock閿?瀹炰緥鍖朩riteLock鏂规硶 */
    public Lock asWriteLock() {
        WriteLockView v;
        return ((v = writeLockView) != null v :
                (writeLockView = new WriteLockView()));
    }

}

瀵逛簬WriteLockView鐨勫疄鐜帮紝涓昏鍖呭惈浠ヤ笅鍑犱釜鏂归潰鐨勫唴瀹癸紝鍏朵腑锛?/p>

  • 鍩烘湰瀹炵幇鏂瑰紡锛氬熀浜嶭ock鎺ュ彛瀹炵幇锛屾彁渚涗簡瀵瑰簲鐨勯攣鑾峰彇鍜岄噴鏀炬搷浣滄柟娉曪紝鍏朵腑锛?
    • lock()鏂规硶锛氫竴鑸ā寮忥紝涓昏閫氳繃StampedLock绫讳腑WriteLock()鏂规硶瀹炵幇
    • lockInterruptibly()鏂规硶锛氬彲涓柇妯″紡锛屼富瑕侀€氳繃StampedLock绫讳腑writeLockInterruptibly()鏂规硶瀹炵幇
    • 鏃犲弬鏁皌ryLock() 鏂规硶锛氬皾璇曡幏鍙栭攣锛屼富瑕佷緷鎹甋tampedLock绫讳腑tryWriteLock() != 0L鏉ュ疄鐜?/li>
    • 鏈夊弬鏁皌ryLock() 鏂规硶锛氬皾璇曡幏鍙栭攣锛屼富瑕佷緷鎹甋tampedLock绫讳腑tryWriteLock(long time, TimeUnit unit) != 0L鏉ュ疄鐜?/li>
    • unlock()鏂规硶锛氶攣鐨勯噴鏀撅紝涓昏閫氳繃StampedLock绫讳腑unstampedUnlockWrite()鏂规硶瀹炵幇
    • newCondition() 鏂规硶锛氫笉鏀寔鏉′欢鍙橀噺鐨勫畾涔夛紝榛樿璁剧疆鎶涘嚭UnsupportedOperationException
  • 鏍稿績澶勭悊鏂规硶锛氫富瑕佹槸鍦⊿tampedLock澶栧眰瀹炵幇鐨勬搷浣滄柟娉曪紝鍏朵腑锛?
    • writeLock()鏂规硶锛氬啓閿佺殑瀹炵幇锛屼富瑕佹牳蹇冮€昏緫鍦╝cquireWrite()鏂规硶
    • tryWriteLock()鏂规硶锛氬皾璇曡幏鍙栧啓閿侊紝鏍稿績澶勭悊閫昏緫鏄牴鎹搴旂殑鏉′欢杩斿洖瀵瑰簲鐨勯攣鐨刜stamp锛屽惁鍒欐姏鍑篲InterruptedException銆?/li>
    • writeLockInterruptibly()鏂规硶锛氬啓閿佺殑鍙腑鏂満鍒跺疄鐜帮紝鏍稿績澶勭悊閫昏緫鏄垽鏂嚎绋嬫槸鍚︿腑鏂互鍙婂埄鐢╝cquireWrite鏂规硶楠岃瘉锛屾潯浠舵垚绔嬫椂锛岃繑鍥為攣鐨刜stamp锛屽惁鍒欐姏鍑篲InterruptedException銆?/li>
    • unstampedUnlockWrite()鏂规硶锛氶噴鏀鹃攣锛屾牳蹇冨鐞嗛€昏緫涓昏鏄€氳繃璋冪敤release(WNode h) 鏂规硶瀹炵幇銆?/li>

2.6 鍩轰簬ReadWriteLock鎺ュ彛瀹炵幇ReadWriteLockView

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?瀹炰緥鍖朢eadWriteLock鏂规硶 */
    final class ReadWriteLockView implements ReadWriteLock {
        /** StampedLock閿?ReadLock鏂规硶 */
        public Lock readLock() { return asReadLock(); }
        /** StampedLock閿?WriteLock鏂规硶 */
        public Lock writeLock() { return asWriteLock(); }
    }

    /** StampedLock閿?瀹炰緥鍖朢eadWriteLock鏂规硶 */
    public ReadWriteLock asReadWriteLock() {
        ReadWriteLockView v;
        return ((v = readWriteLockView) != null v :
                (readWriteLockView = new ReadWriteLockView()));
    }
}


瀵逛簬ReadWriteLockView鐨勫疄鐜帮紝涓昏鍖呭惈涓や釜閮ㄥ垎锛屽叾涓細

  • 鍩轰簬ReadWriteLock鎺ュ彛瀹炵幇锛屼富瑕佹槸瀹炵幇readLock()鍜寃riteLock()鏂规硶
  • 鍦╝sReadWriteLock()鏂规硶涓紝瀹炰緥鍖朢eadWriteLockView瀵硅薄

3. 鍏蜂綋瀹炵幇

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第13张

瀵逛簬StampedLock鐨勫叿浣撳疄鐜帮紝鎴戜滑鍙互浠庡涓嬪嚑涓柟闈㈡媶瑙e紑鏉ュ垎鏋愶細

  • 鍏变韩閿丷eadLock閿佽幏鍙栨搷浣滃疄鐜帮細 闇€瑕佸尯鍒嗘偛瑙傝閿佸拰涔愯璇婚攣鐨勮幏鍙栦釜鏈変笉鍚岋紝涓€鑸湁榛樿鑾峰彇鏂瑰紡鍜屽皾璇曡幏鍙栦袱绉嶆柟寮忋€?/li>
  • 鐙崰閿乄riteLock鍐欓攣鑾峰彇鎿嶄綔瀹炵幇锛?鍐欓攣涓庢偛瑙傝閿佷簰鏂ワ紝涓€鑸湁榛樿鑾峰彇鏂瑰紡鍜屽皾璇曡幏鍙栦袱绉嶆柟寮?/li>
  • 鍏变韩閿丷eadLock閿侀噴鏀炬搷浣滃疄鐜帮細 涓€鑸垎涓哄叏閲婃斁鍜屽崐閲婃斁ReadLock閿佹搷浣滀袱绉嶆柟寮?/li>
  • 鐙崰閿乄riteLock閿侀噴鏀炬搷浣滃疄鐜帮細涓€鑸垎涓哄叏閲婃斁鍜屽崐閲婃斁WriteLock閿佹搷浣滀袱绉嶆柟寮?/li>

鎺ヤ笅鏉ワ紝鎴戜滑渚夸粠鍏蜂綋鐨勪唬鐮佷腑鏉ュ垎鏋愪互涓婂唴瀹圭殑鍩烘湰瀹炵幇锛屼互鏂逛究鎴戜滑姝g‘璁よ瘑鍜屼簡瑙tampedLock閿併€?/p>

3.1 鍏变韩閿丷eadLock璇婚攣鑾峰彇鎿嶄綔瀹炵幇

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?鎮茶璇婚攣-灏濊瘯鑾峰彇閿?榛樿妯″紡锛屼笉鏀寔瓒呮椂鏈哄埗) */
    public long tryReadLock() {

        // 閿佽嚜鏃嬭浆+compareAndSwapLong鏉AS鎿嶄綔鍔犳寔
        for (;;) {
            long s, m, next;

            // [1].鐩存帴杩斿洖0
            if ((m = (s = state) & ABITS) == WBIT)
                return 0L;

                // [2].compareAndSwapLong鏉AS鎿嶄綔鍔犳寔
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                    return next;
            }
                // [3].灏濊瘯鑾峰彇璇婚攣婧㈠嚭澶勭悊
            else if ((next = tryIncReaderOverflow(s)) != 0L)
                return next;
        }
    }

    /** StampedLock閿?鎮茶璇婚攣-灏濊瘯鑾峰彇閿?鎸囧畾妯″紡锛屾敮鎸佽秴鏃舵満鍒? */
    public long tryReadLock(long time, TimeUnit unit)
    throws InterruptedException {
        long s, m, next, deadline;
        long nanos = unit.toNanos(time);
        if (!Thread.interrupted()) {
            if ((m = (s = state) & ABITS) != WBIT) {
                if (m < RFULL) {
                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                        return next;
                }
                else if ((next = tryIncReaderOverflow(s)) != 0L)
                    return next;
            }
            if (nanos <= 0L)
                return 0L;
            if ((deadline = System.nanoTime() + nanos) == 0L)
                deadline = 1L;
            if ((next = acquireRead(true, deadline)) != INTERRUPTED)
                return next;
        }
        throw new InterruptedException();
    }

    /** StampedLock閿?涔愯璇婚攣-灏濊瘯鑾峰彇閿?*/
    public long tryOptimisticRead() {
        long s;
        return (((s = state) & WBIT) == 0L) (s & SBITS) : 0L;
    }
}

瀵逛簬璇婚攣鐨勮幏鍙栨潵璇达紝閮藉睘浜庢槸鍏变韩閿侊紝涓昏鎻愪緵浜嗕互涓嬪嚑绉嶆柟寮忥細

  • 鏃犲弬鏁皌ryReadLock()鏂规硶锛氭偛瑙傝閿佺殑鑾峰彇鏂瑰紡锛岄粯璁ゆā寮忥紝涓嶆敮鎸佽秴鏃舵満鍒?/li>
  • 鏈夊弬鏁皌ryReadLock()鏂规硶锛氭偛瑙傝閿佺殑鑾峰彇鏂瑰紡锛屾寚瀹氬弬鏁版ā寮忥紝鏀寔瓒呮椂鏈哄埗
  • 鏃犲弬鏁皌ryOptimisticRead()鏂规硶锛氫箰瑙傝閿佺殑鑾峰彇鏂瑰紡锛屾病鏈夊姞閿佹搷浣?/li>

3.2 鐙崰閿乄riteLock鍐欓攣鑾峰彇鎿嶄綔瀹炵幇

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {

    /** StampedLock閿?鑾峰彇鍐欓攣鎿嶄綔(涓嶆敮鎸佽秴鏃舵満鍒? */
    public long tryWriteLock() {
        long s, next;
        return ((((s = state) & ABITS) == 0L &&
                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
                next : 0L);
    }

    /** StampedLock閿?鑾峰彇鍐欓攣鎿嶄綔(鏀寔瓒呮椂鏈哄埗) */
    public long tryWriteLock(long time, TimeUnit unit)
    throws InterruptedException {
        long nanos = unit.toNanos(time);
        if (!Thread.interrupted()) {
            long next, deadline;
            if ((next = tryWriteLock()) != 0L)
                return next;
            if (nanos <= 0L)
                return 0L;
            if ((deadline = System.nanoTime() + nanos) == 0L)
                deadline = 1L;
            if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
                return next;
        }
        throw new InterruptedException();
    }

}

瀵逛簬鍐欓攣鐨勮幏鍙栨潵璇达紝閮藉睘浜庢槸鐙崰閿侊紝涓昏鎻愪緵浜嗕互涓嬪嚑绉嶆柟寮忥細

  • 鏃犲弬鏁皌ryWriteLock()鏂规硶锛氶粯璁ゆā寮忥紝涓嶆敮鎸佽秴鏃舵満鍒?/li>
  • 鏈夊弬鏁皌ryWriteLock()鏂规硶锛氭寚瀹氭ā寮忥紝渚濇嵁鍙傛暟鏉ュ疄鐜帮紝鏀寔瓒呮椂鏈哄埗

3.3 鍏变韩閿丷eadLock閲婃斁鎿嶄綔瀹炵幇

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {
    
    /** StampedLock閿?閲婃斁閿佹搷浣?*/
    public void unlock(long stamp) {
        long a = stamp & ABITS, m, s; WNode h;
        while (((s = state) & SBITS) == (stamp & SBITS)) {
            if ((m = s & ABITS) == 0L)
                break;
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = (s += WBIT) == 0L ORIGIN : s;
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return;
            }
            else if (a == 0L || a >= WBIT)
                break;
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                return;
        }
        throw new IllegalMonitorStateException();
    }

    /** StampedLock閿?閲婃斁璇婚攣 */
    public void unlockRead(long stamp) {
        long s, m; WNode h;
        for (;;) {
            if (((s = state) & SBITS) != (stamp & SBITS) ||
                (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
                throw new IllegalMonitorStateException();
            if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    break;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                break;
        }
    }

    /** StampedLock閿?鎮茶璇婚攣-杞崲鍗囩骇骞堕噴鏀惧鐞?*/
    public long tryConvertToReadLock(long stamp) {
        long a = stamp & ABITS, m, s, next; WNode h;
        while (((s = state) & SBITS) == (stamp & SBITS)) {
            if ((m = s & ABITS) == 0L) {
                if (a != 0L)
                    break;
                else if (m < RFULL) {
                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                        return next;
                }
                else if ((next = tryIncReaderOverflow(s)) != 0L)
                    return next;
            }
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = next = s + (WBIT + RUNIT);
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return next;
            }
            else if (a != 0L && a < WBIT)
                return stamp;
            else
                break;
        }
        return 0L;
    }

    /** StampedLock閿?涔愯璇婚攣-杞崲鍗囩骇骞堕噴鏀惧鐞?*/
    public long tryConvertToOptimisticRead(long stamp) {
        long a = stamp & ABITS, m, s, next; WNode h;
        U.loadFence();
        for (;;) {
            if (((s = state) & SBITS) != (stamp & SBITS))
                break;
            if ((m = s & ABITS) == 0L) {
                if (a != 0L)
                    break;
                return s;
            }
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = next = (s += WBIT) == 0L ORIGIN : s;
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return next;
            }
            else if (a == 0L || a >= WBIT)
                break;
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return next & SBITS;
                }
            }
            else if ((next = tryDecReaderOverflow(s)) != 0L)
                return next & SBITS;
        }
        return 0L;
    }

    public boolean tryUnlockRead() {
        long s, m; WNode h;
        while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
            if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return true;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                return true;
        }
        return false;
    }
    
    /** StampedLock閿?灏濊瘯閲婃斁璇婚攣 */
    public boolean tryUnlockRead() {
        long s, m; WNode h;
        while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
            if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return true;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                return true;
        }
        return false;
    }

}

瀵逛簬璇婚攣鐨勯噴鏀炬潵璇达紝涓昏鎻愪緵浜嗕互涓嬪嚑绉嶆柟寮忥細

  • unlock() 鏂规硶锛氫緷鎹攣鐨勭姸鎬乻tatus鏉ュ尮閰嶅搴旈攣鐨剆tamp锛岀劧鍚庨噴鏀鹃攣鎿嶄綔
  • unlockRead()鏂规硶锛?渚濇嵁閿佺殑鐘舵€乻tatus鏉ュ尮閰嶅搴旇閿佺殑stamp锛岀劧鍚庨噴鏀鹃攣鎿嶄綔
  • tryUnlockRead()鏂规硶锛氶噴鏀惧綋鍓嶆寔鏈夌殑璇婚攣锛屼細璁剧疆涓€涓猻tamp鐒跺悗杩斿洖true锛屽惁鍒欙紝杩斿洖false
  • tryConvertToReadLock()鏂规硶锛氫緷鎹攣鐨勭姸鎬乻tatus鏉ュ尮閰嶅搴旇閿佺殑stamp,鐒跺悗鏍规嵁瀵瑰簲鎯呭喌澶勭悊銆傚叾涓細
    • 鍗曞啓閿佹ā寮忥細涓€鑸繑鍥炰竴涓搴旇閿佺殑stamp
    • 鎮茶璇绘ā寮忥細鐩存帴杩斿洖瀵瑰簲璇婚攣鐨剆tamp
    • 涔愯璇绘ā寮忥細闇€瑕佽幏鍙栦竴涓閿侊紝鐒跺悗鏄珛鍗宠繑鍥炲搴旇閿佺殑stamp
  • tryConvertToOptimisticRead(): 渚濇嵁閿佺殑鐘舵€乻tatus鏉ュ尮閰嶅搴旇閿佺殑stamp,鐒跺悗杞崲鍗囩骇澶勭悊閲婃斁銆傚叾涓細
    • 鎮茶璇绘ā寮忥細灞炰簬涓€鑸閿佹ā寮忥紝杩斿洖鐨勬槸妫€娴嬪埌瀵瑰簲璇婚攣鐨剆tamp
    • 涔愯璇绘ā寮忥細闇€瑕佽繑鍥為€氳繃楠岃瘉鐨勫搴旇閿佺殑stamp

3.4 鐙崰閿乄riteLock鍐欓攣閲婃斁鎿嶄綔瀹炵幇

/** StampedLock閿?鏈€鏃╁湪JDK1.8涓疄鐜扮殑 */
public class StampedLock implements java.io.Serializable {


    /** StampedLock閿?閿侀噴鏀炬柟娉?涓€鑸柟娉? */
    public void unlock(long stamp) {
        long a = stamp & ABITS, m, s; WNode h;
        while (((s = state) & SBITS) == (stamp & SBITS)) {
            if ((m = s & ABITS) == 0L)
                break;
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = (s += WBIT) == 0L ORIGIN : s;
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return;
            }
            else if (a == 0L || a >= WBIT)
                break;
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L)
                return;
        }
        throw new IllegalMonitorStateException();
    }

    /** StampedLock閿?鍐欓攣閲婃斁鏂规硶 */
    public void unlockWrite(long stamp) {
        WNode h;
        if (state != stamp || (stamp & WBIT) == 0L)
            throw new IllegalMonitorStateException();
        state = (stamp += WBIT) == 0L ORIGIN : stamp;
        if ((h = whead) != null && h.status != 0)
            release(h);
    }

    /** StampedLock閿?鍐欓攣杞崲鍗囩骇澶勭悊骞堕噴鏀鹃攣 */
    public long tryConvertToWriteLock(long stamp) {
        long a = stamp & ABITS, m, s, next;
        while (((s = state) & SBITS) == (stamp & SBITS)) {
            if ((m = s & ABITS) == 0L) {
                if (a != 0L)
                    break;
                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
                    return next;
            }
            else if (m == WBIT) {
                if (a != m)
                    break;
                return stamp;
            }
            else if (m == RUNIT && a != 0L) {
                if (U.compareAndSwapLong(this, STATE, s,
                                         next = s - RUNIT + WBIT))
                    return next;
            }
            else
                break;
        }
        return 0L;
    }

    /** StampedLock閿?unlockWrite鐨勬牳蹇冨疄鐜?*/
    private void release(WNode h) {
        if (h != null) {
            WNode q; Thread w;
            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
            if ((q = h.next) == null || q.status == CANCELLED) {
                for (WNode t = wtail; t != null && t != h; t = t.prev)
                    if (t.status <= 0)
                        q = t;
            }
            if (q != null && (w = q.thread) != null)
                U.unpark(w);
        }
    }

}

瀵逛簬鍐欓攣鐨勯噴鏀炬潵璇达紝涓昏鎻愪緵浜嗕互涓嬬鏂瑰紡锛?/p>

  • unlock() 鏂规硶锛氫緷鎹攣鐨勭姸鎬乻tatus鏉ュ尮閰嶅搴旈攣鐨剆tamp锛岀劧鍚庨噴鏀鹃攣鎿嶄綔
  • unlockWrite()鏂规硶锛氫緷鎹攣鐨勭姸鎬乻tatus鏉ュ尮閰嶅搴斿啓閿佺殑stamp锛岀劧鍚庨噴鏀鹃攣鎿嶄綔
  • tryUnlockWrite()鏂规硶锛氶噴鏀惧綋鍓嶆寔鏈夌殑鍐欓攣锛屼細璁剧疆涓€涓猻tamp鐒跺悗杩斿洖true锛屽惁鍒欙紝杩斿洖false
  • tryConvertToWriteLock()鏂规硶锛氫緷鎹攣鐨勭姸鎬乻tatus鏉ュ尮閰峴tamp锛屾牴鎹搴旈攣鐨勫仛鍗囩骇澶勭悊銆傚叾涓細
    • 鍗曞啓閿佹ā寮忥細鐩存帴杩斿洖瀵瑰簲鐨勫啓閿佹爣璁皊tamp
    • 璇诲啓閿佹ā寮忥細闇€瑕侀噴鏀捐閿侀攣锛屽苟杩斿洖瀵瑰簲鐨勫啓閿佹爣璁皊tamp
    • 涔愯璇绘ā寮忥細鐩存帴杩斿洖瀵瑰簲鐨勫啓閿佹爣璁皊tamp

缁间笂鎵€杩帮紝StampedLock閿佹湰璐ㄤ笂渚濈劧鏄竴绉嶈鍐欓攣锛屽彧鏄病鏈夊熀浜嶢QS鍩虹鍚屾鍣ㄦ潵瀹炵幇锛屾槸鑷畾涔夊皝瑁匒PI鎿嶄綔瀹炵幇鐨勩€?/p>

鍐欏湪鏈€鍚?/h2>
Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之StampedLock锁的设计思想与实现原理 (三),第14张

閫氳繃瀵笿ava棰嗗煙涓紝JDK鍐呴儴鎻愪緵鐨勫悇绉嶉攣鐨勫疄鐜版潵鐪嬶紝涓€鐩村洿缁曠殑鏍稿績涓昏杩樻槸鍩轰簬AQS鍩虹鍚屾鍣ㄦ潵瀹炵幇鐨勶紝浣嗘槸AQS鍩虹鍚屾鍣ㄤ笉鏄竴绉嶉潪瀹冧笉鍙殑鎶€鏈爣鍑嗚鑼冿紝鏇村鐨勫彧鏄竴濂楁妧鏈弬鑰冩寚鍗椼€?/p>

浣嗘槸锛屽疄闄呬笂锛孞ava瀵逛簬閿佺殑瀹炵幇涓庤繍鐢ㄨ繙杩滀笉姝㈣繖浜涳紝杩樻湁鐩镐綅鍣?Phaser)鍜屼氦鎹㈠櫒(Exchanger),浠ュ強鍦↗ava JDK1.8鐗堟湰涔嬪墠骞跺彂瀹瑰櫒ConcurrentHashMap涓娇鐢ㄧ殑鍒嗘閿?Segment)銆?/p>

涓嶈鏄綍绉嶅疄鐜板拰搴旂敤锛屽湪Java骞跺彂缂栫▼棰嗗煙鏉ヨ锛岄兘鏄洿缁曠嚎绋嬪畨鍏ㄩ棶棰樼殑瑙掑害鍘昏€冭檻鐨勶紝鍙槸閽堝浜庡悇绉嶅悇鏍风殑涓氬姟鍦烘櫙鍋氱殑鍏蜂綋鐨勫疄鐜般€?/p>

涓€瀹氭剰涔変笂鏉ヨ锛屽绾跨▼鍔犻攣鍙槸骞跺彂缂栫▼鐨勫疄鐜版柟寮忎箣涓€锛岀浉瀵逛簬瀹為檯搴旂敤鏉ヨ锛孞ava棰嗗煙涓殑閿侀兘鍙槸涓€绉嶅崟涓€搴旂敤鐨勯攣锛屽彧鏄粰鎴戜滑鎺屾彙Java骞跺彂缂栫▼鎻愪緵涓€绉嶆€濇兂娌★紝涓夎█涓よ涔熶笉鍙兘璇﹀敖銆?/p>

鍒版涓烘锛岃繖绠楁槸瀵逛簬Java棰嗗煙涓苟鍙戦攣鐨勬渶缁堢珷锛屾枃涓〃杩板潎涓轰釜浜虹湅娉曞拰涓汉鐞嗚В锛屽鏈変笉鍒颁箣澶勶紝蹇樿璋呰В涔熻缁欎簣鎵硅瘎鎸囨銆?/p>

鏈€鍚庯紝鎶€鏈爺绌朵箣璺换閲嶈€岄亾杩滐紝鎰挎垜浠啲鐨勬瘡涓€涓€氬锛岄兘鎾戝緱璧锋垜浠兂鍦ㄨ繖鏉¤矾涓婅蛋涓嬪幓鐨勫媷姘旓紝鏈潵浠嶇劧鍙湡锛屼笌鍚勪綅绋嬪簭缂栫▼鍚涘叡鍕夛紒

鐗堟潈澹版槑锛氭湰鏂囦负鍗氫富鍘熷垱鏂囩珷锛岄伒寰浉鍏崇増鏉冨崗璁紝濡傝嫢杞浇鎴栬€呭垎浜闄勪笂鍘熸枃鍑哄閾炬帴鍜岄摼鎺ユ潵婧愩€?/p>


https://www.xamrdz.com/backend/3ee1940508.html

相关文章: