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

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

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

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

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

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

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

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

鍏冲仴鏈

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第8张

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

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

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

鍥?ReentrantReadWriteLock(璇诲啓閿?鐨勮璁′笌瀹炵幇

鍦↗ava棰嗗煙涓紝ReentrantReadWriteLock(璇诲啓閿?鏄拡瀵逛簬Java澶氱嚎绋嬪苟鍙戞帶鍒朵腑寮曞叆涓€涓叡浜攣瀹氫箟璇绘搷浣滀笌鐙崰閿佸畾涔夎鎿嶄綔绛夊満鏅叡鍚岀粍鍚堟瀯鎴愪竴鎶婇攣鏉ユ彁楂樺苟鍙戯紝涓昏鏄熀浜庡唴缃殑AQS鍩虹鎶借薄闃熷垪鍚屾鍣ㄥ疄鐜扮殑涓€绉嶅苟鍙戞帶鍒跺伐鍏风被銆?/p>

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

<br />閫氳繃ReentrantReadWriteLock绫昏兘鑾峰彇璇婚攣鍜屽啓閿侊紝瀹冪殑璇婚攣鏄彲浠ュ绾跨▼鍏变韩鐨勫叡浜攣锛岃€屽畠鐨勫啓閿佹槸鎺掍粬閿侊紝鍦ㄨ鍗犳椂涓嶅厑璁稿叾浠栫嚎绋嬪啀鎶㈠崰鎿嶄綔銆?/p>

1. 璁捐鎬濇兂

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

<br />涓€鑸潵璇达紝鍦ㄤ竴浜涚壒娈婄殑鍦烘櫙涓紝姣斿瀵逛簬鏁版嵁鐨勮鍜屽啓鎿嶄綔锛屼负鎻愰珮骞跺彂鎬ц兘锛屾€讳細寮曞叆鍏变韩閿佸拰鐙韩閿佹潵鍏卞悓缁勬垚涓€鎶婇攣锛岄€氬父鎯呭喌涓嬶紝鎴戜滑鎶婅繖绫婚攣鎴愪负璇诲啓閿?ReadWriteLock) 銆?lt;br />绠€鍗曟潵璇达紝灏辨槸涓昏鑰冭檻璇诲拰鍐欐搷浣滐紝璇绘搷浣滀笉浼氫慨鏀规暟鎹紝鍙互鍒╃敤澶氫釜绾跨▼杩涜璇绘搷浣滐紝涓€鑸噰鐢ㄥ叡浜攣瀹炵幇锛涜€屽啓鎿嶄綔浼氭敼鍙樻暟鎹湰韬紝鍙兘鍏佽涓€涓嚎绋嬭繘琛屾搷浣滐紝鍥犳閲囩敤鐙韩閿佸疄鐜般€?lt;br />璇诲啓閿?ReadWriteLock) 鏈€澶х殑涓€涓壒鐐瑰氨鏄湪鍐呴儴缁存姢涓€瀵归攣锛屼竴鎶婅閿?ReadLock) 锛屼竴鎶婂啓閿?WriteLock) 銆傚叾涓紝瀵逛簬绾跨▼鎸佹湁鐨勬儏鍐垫潵璇达紝绠€鍗曞彲浠ユ€荤粨涓衡€滆鍏变韩锛屽啓鐙崰鈥濄€?/p>

1.1 璇诲啓閿佺殑鍩烘湰鐞嗚

铏界劧璇诲啓閿?ReadWriteLock) 涔嬮棿鏄湁鍏崇郴鐨勶細鍚屼竴鏃跺埢涓嶅厑璁歌閿佸拰鍐欓攣鍚屾椂琚姠鍗狅紝浜岃€呬箣闂存槸浜掓枼鐨勩€?lt;br />鍋囪鐜板湪鏈塏涓嚎绋嬶紝涓昏浠嶵(1),T(2)锛?..锛屼竴鐩村埌T(N)涓嚎绋嬶紝鍦ㄨ鍐欓攣鐨勬搷浣滄儏鍐靛涓嬶紝鍏朵腑锛?/p>

  • 澶氳妯″紡(澶氳鍏变韩)锛歍(N) 涓嚎绋嬪彲浠ュ悓鏃舵妸鎸佸苟鑾峰彇璇婚攣锛屽亣璁綯(1)绾跨▼鎴愬姛鑾峰彇骞舵寔鏈夎閿侊紝T(2)绾跨▼鍜屽悗缁殑T(N)涓嚎绋嬩緷鐒跺彲浠ユ垚鍔熻幏鍙栬閿侊紝鍗充娇T(1)绾跨▼娌℃湁閲婃斁鎸佹湁鐨勮閿併€?/li>
  • 璇诲啓妯″紡(璇诲啓浜掓枼)锛氬亣璁綯(1)绾跨▼鎴愬姛鑾峰彇骞舵寔鏈夎閿侊紝T(2)绾跨▼鍜屽悗缁殑T(N)涓嚎绋嬩究涓嶈兘鎴愬姛鑾峰彇涓旀寔鏈夊啓閿侊紝闄ら潪T(1)绾跨▼宸茬粡閲婃斁鎸佹湁鐨勮閿併€?/li>
  • 鐙啓妯″紡(鍗曞啓鐙崰)锛氬亣璁綯(1)绾跨▼鎴愬姛鑾峰彇骞舵寔鏈夊啓閿侊紝T(2)绾跨▼鍜屽悗缁殑T(N)涓嚎绋嬩究涓嶈兘鎴愬姛鑾峰彇涓旀寔鏈夎閿佸拰鍐欓攣锛屽彧鑳界瓑寰呯瓑寰匱(1)绾跨▼閲婃斁瀹屾寔鏈夌殑鍐欓攣锛屾墠鑳界户缁線涓嬫墽琛屻€?/li>

浠庝竴瀹氭剰涔変笂璁诧紝鏍规嵁璇诲啓閿佹搷浣滅殑鎯呭喌鐨勬€ц川鍒嗘瀽锛岃幏鍙栬閿佸拰鍐欓攣鐨勬潯浠跺彲浠ュぇ鑷存€荤粨涓猴細

  • 鑾峰彇璇婚攣鐨勬潯浠讹細褰撳墠浠讳綍绾跨▼娌℃湁鎴愬姛鑾峰彇涓斿凡缁忔寔鏈夊啓閿佺殑鎯呭喌锛屾墠鍙兘鑾峰彇骞舵寔鏈夎閿併€?/li>
  • 鑾峰彇鍐欓攣鐨勬潯浠讹細褰撳墠浠讳綍绾跨▼娌℃湁鎴愬姛鑾峰彇涓斿凡缁忔寔鏈夊啓閿佸拰璇婚攣鐨勬儏鍐碉紝鎵嶅彲鑳借幏鍙栧苟鎸佹湁鍐欓攣銆?/li>

浣嗘槸鍦ㄦ煇浜涙儏鍐典笅锛屽彲鑳藉瓨鍦ㄦ煇涓嚎绋嬪凡缁忚幏鍙栧苟鎸佹湁璇婚攣锛屽笇鏈涜兘澶熻幏鍙栧啓閿侊紝骞朵笖鍦ㄥ凡缁忛噴鏀捐閿佹椂锛岄€氬父鎯呭喌涓嬫垜浠О涔嬩负璇诲啓閿佺殑鍗囩骇銆?lt;br />褰撶劧锛屾湁鍗囩骇灏变細鏈夐檷绾э紝涓庝箣瀵瑰簲鐨勫氨鏄鍐欓攣鐨勯檷绾э紝涓昏鎻忚堪鐨勬槸鏌愪釜绾跨▼宸茬粡鑾峰彇骞舵寔鏈夊啓閿侊紝甯屾湜鑳藉鑾峰彇璇婚攣锛屽苟涓斿凡缁忛噴鏀惧啓閿併€?lt;br />涓€鑸潵璇达紝瀵逛簬璇诲啓閿佺殑鍗囩骇涓庨檷绾э紝鎴戜滑涓€鑸渶瑕佹敞鎰忕殑浠ヤ笅涓や釜闂锛屽叾涓細

  • 璇诲啓閿佺殑鍗囩骇锛氭寚鐨勬槸璇婚攣鍗囩骇涓哄啓閿佺殑鎯呭喌锛岄渶瑕佹弧瓒虫煇涓嚎绋嬪繀椤绘槸鍞竴鎷ユ湁璇婚攣鐨勭嚎绋嬬殑鏉′欢锛屽惁鍒欐棤娉曞崌绾с€?/li>
  • 璇诲啓閿佺殑闄嶇骇锛氭寚鐨勬槸鍐欓攣闄嶇骇涓鸿閿佺殑鎯呭喌锛屾病鏈変粈涔堟潯浠堕檺鍒讹紝鍐欓攣鏄嫭鍗犻攣锛屽叾鎸佹湁绾跨▼鏄敮涓€鐨勪笖涓嶄細瀛樺湪璇婚攣鎸佹湁绾跨▼鐨勬儏鍐碉紝鍙互鐩存帴骞虫粦鍗囩骇璇婚攣銆?/li>

1.2 璇诲啓閿佺殑瀹炵幇鎬濇兂

ReentrantReadWriteLock鏈€鏃╂槸鍦↗DK1.5鐗堟湰涓彁渚涚殑锛屼粠璁捐鎬濇兂涓婃潵鐪嬶紝涓昏鍖呮嫭鍚屾鍣ㄧ殑宸ヤ綔妯″紡锛岃閿佸拰鍐欓攣绛?涓牳蹇冭绱犮€傚叾涓細

  • 瀹炵幇ReadWriteLock鎺ュ彛 锛氫富瑕佸熀浜嶳eadWriteLock鎺ュ彛API瀹炵幇瀵瑰簲鏂规硶锛屼富瑕佹槸瀹炵幇writeLock()鏂规硶鍜宺eadLock() 鏂规硶锛屽叾涓瓀riteLock()鏂规硶琛ㄧず鑾峰彇鍐欓攣锛宺eadLock() 鏂规硶琛ㄧず鑾峰彇璇婚攣銆?/li>
  • 鍚屾鍣ㄧ殑宸ヤ綔妯″紡锛氬熀浜嶢QS鍩虹鎶借薄闃熷垪鍚屾鍣ㄥ皝瑁呭唴缃疄鐜颁竴涓潤鎬佺殑鍐呯疆鍚屾鍣ㄦ娊璞$被锛岀劧鍚庡熀浜庤繖涓娊璞$被鍒嗗埆瀹炵幇浜嗗叕骞冲悓姝ュ櫒鍜岄潪鍏钩鍚屾鍣紝鐢ㄦ潵鎸囧畾鍜屾弿杩板悓姝ュ櫒宸ヤ綔妯″紡鏄叕骞虫ā寮忚繕鏄潪鍏钩妯″紡銆?/li>
  • 鍏钩/闈炲叕骞虫ā寮忥細涓昏鎻忚堪鐨勬槸澶氫釜绾跨▼鍦ㄥ悓鏃惰幏鍙栭攣鏃舵槸鍚︽寜鐓у厛鍒板厛寰楃殑椤哄簭鑾峰彇閿侊紝濡傛灉鏄垯涓哄叕骞虫ā寮忥紝鍚﹀垯涓洪潪鍏钩妯″紡銆?/li>
  • 鍐呯疆涓や釜闈欐€佸叕鏈夊唴閮ㄧ被锛氬畾涔変簡璇婚攣鍜屽啓閿侀潤鎬佸叕鏈夊唴閮ㄧ被锛屽苟涓旈兘鏀寔鍏钩/闈炲叕骞虫ā寮忥紝鏈川閮芥槸鍩轰簬AQS鍩虹鎶借薄闃熷垪鍚屾鍣ㄥ疄鐜般€?/li>
  • 缁存姢鍏变韩鐘舵€佸彉閲忥細 涓昏鏄熀浜庝竴涓狝QS鍩虹鎶借薄闃熷垪鍚屾鍣ㄦ潵瀹炵幇璇婚攣鍜屽啓閿侊紝瑕佹眰鍏辩敤涓€涓叡浜姸鎬佸彉閲忋€?/li>

2. 鍩烘湰瀹炵幇

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

鍦≧eentrantReadWriteLock绫诲湪JDK1.8鐗堟湰涓紝瀵逛簬ReentrantReadWriteLock鐨勫熀鏈疄鐜板涓嬶細

public class ReentrantReadWriteLock
    implements ReadWriteLock, java.io.Serializable {

        private static final long serialVersionUID = -6992448646407690164L;

        /** ReentrantReadWriteLock閿?鍐呴儴ReadLock绫?*/
        private final ReentrantReadWriteLock.ReadLock readerLock;

        /** ReentrantReadWriteLock閿?鍐呴儴WriteLock绫?*/
        private final ReentrantReadWriteLock.WriteLock writerLock;

        /** ReentrantReadWriteLock閿?鍐呴儴鍚屾鍣?*/
        final Sync sync; 

        /** ReentrantReadWriteLock閿?鍩轰簬AQS灏佽鍐呴儴鍚屾鍣?*/
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = 6317671515068378041L;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?begin*/

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍏变韩鐘舵€佺Щ鍔ㄤ綅鏁?6 */
            static final int SHARED_SHIFT   = 16;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勭姸鎬佸ぇ灏?/
            static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勬渶澶ф鏁?/
            static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍐欓攣鐨勬帺鐮?/
            static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鏈湴瀛樺偍璇婚攣娆℃暟*/
            private transient ThreadLocalHoldCounter readHolds;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣鐨勭姸鎬佺爜鍊?/
            private transient HoldCounter cachedHoldCounter;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?绾跨▼鍙橀噺*/
            private transient Thread firstReader = null;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?棣栨璇婚攣娆℃暟*/
            private transient int firstReaderHoldCount;

            /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?end*/

            Sync() {
                readHolds = new ThreadLocalHoldCounter();
                setState(getState()); // ensures visibility of readHolds
            }

            /** ReentrantReadWriteLock閿?璇婚攣鏍囪*/
            abstract boolean readerShouldBlock();

            /** ReentrantReadWriteLock閿?璇婚攣鏍囪*/
            abstract boolean writerShouldBlock();

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



        /** ReentrantReadWriteLock閿?鏃犲弬鏁版瀯閫?榛樿闈炲叕骞虫ā寮? */
        public ReentrantReadWriteLock() {
            this(false);
        }

        /** ReentrantReadWriteLock閿?鏈夊弬鏁版瀯閫?鍙€夊叕骞?闈炲叕骞虫ā寮? */
        public ReentrantReadWriteLock(boolean fair) {
            sync = fair new FairSync() : new NonfairSync();
            readerLock = new ReadLock(this);
            writerLock = new WriteLock(this);
        }

        /** ReentrantReadWriteLock閿?鑾峰彇鍐欓攣 */
        public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }      
        /** ReentrantReadWriteLock閿?鑾峰彇璇婚攣 */
        public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }


        /** ReentrantReadWriteLock閿?瀹炰緥鍖朥nsafe鏀寔 */
        private static final sun.misc.Unsafe UNSAFE;

        /** ReentrantReadWriteLock閿?绾跨▼鍋忕Щ閲?*/
        private static final long TID_OFFSET;

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        static final long getThreadId(Thread thread) {
            return UNSAFE.getLongVolatile(thread, TID_OFFSET);
        }

        /** ReentrantReadWriteLock閿?鍙嶅皠鏈哄埗瀹炰緥鍖朥nsafe */
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> tk = Thread.class;
                TID_OFFSET = UNSAFE.objectFieldOffset
                    (tk.getDeclaredField("tid"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
  • 鍐呴儴鍚屾鍣細鍩轰簬AQS鍩虹鍚屾鍣ㄥ皝瑁呭拰瀹氫箟浜嗕竴涓潤鎬佸唴閮⊿ync鎶借薄绫?/li>
  • 鍚屾鍣ㄥ伐浣滄ā寮忥細鎻愪緵浜?2涓瀯閫犳柟娉曪紝鍏朵腑鏃犲弬鏁版瀯閫犳柟娉曡〃绀虹殑鏄粯璁ょ殑宸ヤ綔妯″紡锛屾湁鍙傛暟鏋勯€犳柟娉曚富瑕佷緷鎹弬鏁版潵瀹炵幇鎸囧畾鐨勫伐浣滄ā寮?/li>
  • 鍏钩/闈炲叕骞虫ā寮忥細涓昏鏄熀浜嶴ync鎶借薄绫诲皝瑁匩onfairSync闈炲叕骞冲悓姝ュ櫒鍜屽皝瑁匩onfairSync闈炲叕骞冲悓姝ュ櫒鏉ュ疄鐜般€?/li>
  • 鍐呯疆涓や釜鍐呴儴绫伙細涓昏鏄疄鐜颁簡ReadLock绫诲拰WriteLock绫伙紝鍏朵腑ReadLock绫诲搴旂潃璇婚攣锛學riteLock绫诲搴旂潃鍐欓攣銆?/li>

2.1 鍩轰簬AQS鍚屾鍣ㄥ皝瑁呴潤鎬佸唴閮⊿ync鎶借薄绫?/h4>
/** ReentrantReadWriteLock閿?鍩轰簬AQS灏佽鍐呴儴鍚屾鍣?*/
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 6317671515068378041L;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?begin */

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍏变韩鐘舵€佺Щ鍔ㄤ綅鏁?6 */
    static final int SHARED_SHIFT   = 16;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勭姸鎬佸ぇ灏?/
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勬渶澶ф鏁?/
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍐欓攣鐨勬帺鐮?/
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鏈湴瀛樺偍璇婚攣娆℃暟*/
    private transient ThreadLocalHoldCounter readHolds;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣鐨勭姸鎬佺爜鍊?/
    private transient HoldCounter cachedHoldCounter;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?绾跨▼鍙橀噺*/
    private transient Thread firstReader = null;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?棣栨璇婚攣娆℃暟*/
    private transient int firstReaderHoldCount;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?end*/

    Sync() {
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }


    /** ReentrantReadWriteLock閿?璇婚攣鏍囪*/
    abstract boolean readerShouldBlock();

    /** ReentrantReadWriteLock閿?璇婚攣鏍囪*/
    abstract boolean writerShouldBlock();

    /** ReentrantReadWriteLock閿?鐙崰妯″紡鑾峰彇璇婚攣*/
    protected final boolean tryRelease(int releases) {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int nextc = getState() - releases;
        boolean free = exclusiveCount(nextc) == 0;
        if (free)
            setExclusiveOwnerThread(null);
        setState(nextc);
        return free;
    }

    /** ReentrantReadWriteLock閿?鐙崰妯″紡閲婃斁閿?/
    protected final boolean tryAcquire(int acquires) {

        Thread current = Thread.currentThread();
        int c = getState();
        int w = exclusiveCount(c);
        if (c != 0) {
            // (Note: if c != 0 and w == 0 then shared count != 0)
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w + exclusiveCount(acquires) > MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            // Reentrant acquire
            setState(c + acquires);
            return true;
        }
        if (writerShouldBlock() ||
            !compareAndSetState(c, c + acquires))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    /** ReentrantReadWriteLock閿?鍏变韩妯″紡閲婃斁閿?/
    protected final boolean tryReleaseShared(int unused) {
        Thread current = Thread.currentThread();
        if (firstReader == current) {
            // assert firstReaderHoldCount > 0;
            if (firstReaderHoldCount == 1)
                firstReader = null;
            else
                firstReaderHoldCount--;
        } else {
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                rh = readHolds.get();
            int count = rh.count;
            if (count <= 1) {
                readHolds.remove();
                if (count <= 0)
                    throw unmatchedUnlockException();
            }
            --rh.count;
        }
        for (;;) {
            int c = getState();
            int nextc = c - SHARED_UNIT;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
        }
    }

    /** ReentrantReadWriteLock閿?鍏变韩妯″紡鑾峰彇閿?/
    protected final int tryAcquireShared(int unused) {

        Thread current = Thread.currentThread();
        int c = getState();
        if (exclusiveCount(c) != 0 &&
            getExclusiveOwnerThread() != current)
            return -1;
        int r = sharedCount(c);
        if (!readerShouldBlock() &&
            r < MAX_COUNT &&
            compareAndSetState(c, c + SHARED_UNIT)) {
            if (r == 0) {
                firstReader = current;
                firstReaderHoldCount = 1;
            } else if (firstReader == current) {
                firstReaderHoldCount++;
            } else {
                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                    cachedHoldCounter = rh = readHolds.get();
                else if (rh.count == 0)
                    readHolds.set(rh);
                rh.count++;
            }
            return 1;
        }
        return fullTryAcquireShared(current);
    }

    /** ReentrantReadWriteLock閿?鍏变韩妯″紡鑾峰彇閿?/
    final int fullTryAcquireShared(Thread current) {

        HoldCounter rh = null;
        for (;;) {
            int c = getState();
            if (exclusiveCount(c) != 0) {
                if (getExclusiveOwnerThread() != current)
                    return -1;
                // else we hold the exclusive lock; blocking here
                // would cause deadlock.
            } else if (readerShouldBlock()) {
                // Make sure we're not acquiring read lock reentrantly
                if (firstReader == current) {
                    // assert firstReaderHoldCount > 0;
                } else {
                    if (rh == null) {
                        rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current)) {
                            rh = readHolds.get();
                            if (rh.count == 0)
                                readHolds.remove();
                        }
                    }
                    if (rh.count == 0)
                        return -1;
                }
            }
            if (sharedCount(c) == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, c + SHARED_UNIT)) {
                if (sharedCount(c) == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    if (rh == null)
                        rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                    cachedHoldCounter = rh; // cache for release
                }
                return 1;
            }
        }
    }

    /** ReentrantReadWriteLock閿?鍒ゆ柇鏄惁鐙崰妯″紡*/
    protected final boolean isHeldExclusively() {
        return getExclusiveOwnerThread() == Thread.currentThread();
    }

    // Methods relayed to outer class

    /** ReentrantReadWriteLock閿?瀹氫箟鏉′欢鍙橀噺*/
    final ConditionObject newCondition() {
        return new ConditionObject();
    }

    /** ReentrantReadWriteLock閿?鑾峰彇褰撳墠閿佺殑鎸佹湁鑰?/
    final Thread getOwner() {
        // Must read state before owner to ensure memory consistency
        return ((exclusiveCount(getState()) == 0) ?
                null :
                getExclusiveOwnerThread());
    }

    /** ReentrantReadWriteLock閿?鑾峰彇璇婚攣娆℃暟缁熻*/
    final int getReadLockCount() {
        return sharedCount(getState());
    }

    /** ReentrantReadWriteLock閿?鍒ゆ柇鏄惁鏄啓閿?/
    final boolean isWriteLocked() {
        return exclusiveCount(getState()) != 0;
    }

    /** ReentrantReadWriteLock閿?鑾峰彇鍐欓攣鎸佹湁娆℃暟缁熻*/
    final int getWriteHoldCount() {
        return isHeldExclusively() exclusiveCount(getState()) : 0;
    }

    /** ReentrantReadWriteLock閿?鑾峰彇璇婚攣娆℃寔鏈夋暟缁熻*/
    final int getReadHoldCount() {
        if (getReadLockCount() == 0)
            return 0;

        Thread current = Thread.currentThread();
        if (firstReader == current)
            return firstReaderHoldCount;

        HoldCounter rh = cachedHoldCounter;
        if (rh != null && rh.tid == getThreadId(current))
            return rh.count;

        int count = readHolds.get().count;
        if (count == 0) readHolds.remove();
        return count;
    }

    /** ReentrantReadWriteLock閿?鑾峰彇璇婚攣*/
    final boolean tryReadLock() {
        Thread current = Thread.currentThread();
        for (;;) {
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return false;
            int r = sharedCount(c);
            if (r == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return true;
            }
        }
    }

    /** ReentrantReadWriteLock閿?鑾峰彇鍐欓攣*/
    final boolean tryWriteLock() {
        Thread current = Thread.currentThread();
        int c = getState();
        if (c != 0) {
            int w = exclusiveCount(c);
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
        }
        if (!compareAndSetState(c, c + 1))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    /** ReentrantReadWriteLock閿?娴佸鐞?/
    private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        readHolds = new ThreadLocalHoldCounter();
        setState(0); // reset to unlocked state
    }

    /** ReentrantReadWriteLock閿?鑾峰彇鐘舵€?/
    final int getCount() { return getState(); }

}
  • 瀹炵幇鏂瑰紡锛?涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄦ潵瀹炵幇锛屽叾涓皝瑁呮娊璞′簡readerShouldBlock()鏂规硶鍜寃riterShouldBlock()鏂规硶锛岀敤浜庢爣璁板綋鍓嶈姹傜殑绾跨▼鏄幏鍙栦粈涔堢被鍨嬬殑閿併€傚叾涓細
    • readerShouldBlock()鏂规硶锛氫緷鎹爣璁拌繑鍥炵殑鏄痶rue锛屾爣璁扮嚎绋嬭幏鍙栫殑鏄疪eadLock閿?/li>
    • writerShouldBlock()鏂规硶锛氫緷鎹爣璁拌繑鍥炵殑鏄痶rue锛屾爣璁扮嚎绋嬭幏鍙栫殑鏄疻riteLock閿?/li>
  • 缁存姢鍏辩敤鐘舵€佸彉閲? 瀵逛簬鍏变韩鐘舵€佸彉閲忕殑瀹炵幇锛屼富瑕佹槸鍦ㄥ唴閮ㄧ殑鍚屾鍣ㄤ腑Sync绫讳腑瀹氫箟HoldCounter绫诲拰ThreadLocalHoldCounter绫诲疄鐜扮殑锛屽叾涓畾涔変簡涓€鍫嗗父閲忥紝缁熻璇诲啓閿佺姸鎬佸€肩殑sharedCount()鏂规硶鍜宔xclusiveCount()鏂规硶銆?/li>
  • 璇诲啓閿佺殑涓昏鏂规硶锛?涓昏鏄彁渚涗簡tryReadLock()鏂规硶鍜宼ryWriteLock()鏂规硶锛屽叾涓細
    • tryReadLock()鏂规硶锛氳幏鍙栬閿佹柟娉曪紝鏍稿績澶勭悊鏄嚜鏃?compareAndSetState()鏂规硶鏉ュ鐞?/li>
    • tryWriteLock()鏂规硶锛氳幏鍙栧啓閿佹柟娉曪紝鏍稿績澶勭悊鏄€氳繃compareAndSetState()鏂规硶鏉ュ鐞?/li>
  • 璇诲啓閿佺殑鑾峰彇鏂瑰紡锛氬熀浜嶢QS鍩虹鍚屾鍣ㄦ潵瀹炵幇瀵逛簬鍏变韩妯″紡鍜岀嫭浜ā寮忎袱绉嶆儏鍐碉紝閮芥彁渚涗簡瀵瑰簲鐨勬柟娉曘€傚叾涓細
    • tryAcquire()鏂规硶锛氱嫭浜ā寮忚幏鍙栭攣鏂规硶锛岃繖閲屼富瑕侀拡瀵筗riteLock閿侊紝鏍稿績澶勭悊鏄€氳繃AQS鍩虹鍚屾鍣ㄤ腑compareAndSetState()鏂规硶鏉ュ鐞嗭紝瀹炵幇鐘舵€佸彉閲忕殑鎿嶄綔
    • tryAcquireShared() 鏂规硶锛氬叡浜ā寮忚幏鍙栭攣鏂规硶锛岃繖閲屼富瑕佸搴擱eadLock閿侊紝鏍稿績澶勭悊鏄€氳繃AQS鍩虹鍚屾鍣ㄤ腑compareAndSetState()鏂规硶鏉ュ鐞嗭紝瀹炵幇鐘舵€佸彉閲忕殑鎿嶄綔
  • 璇诲啓閿佺殑閲婃斁鏂瑰紡锛氬熀浜嶢QS鍩虹鍚屾鍣ㄦ潵瀹炵幇瀵逛簬鍏变韩妯″紡鍜岀嫭浜ā寮忎袱绉嶆儏鍐碉紝閮芥彁渚涗簡瀵瑰簲鐨勬柟娉曘€傚叾涓細
    • tryRelease(int releases) 鏂规硶锛氱嫭浜ā寮忛噴鏀鹃攣鏂规硶
    • tryReleaseShared(int unused) 鏂规硶锛氬叡浜ā寮忛噴鏀鹃攣鏂规硶锛屾牳蹇冨鐞嗘槸鑷棆+compareAndSetState()鏂规硶鏉ュ鐞?/li>
  • 鍏朵粬鏂规硶锛氫富瑕佽繕鎻愪緵浜嗕竴浜涙瘮杈冨父瑙勭殑鏂规硶锛屽叾涓細
    • getCount() 鏂规硶锛氫富瑕佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄦ潵鑾峰彇鐘舵€佸彉閲?/li>
    • getOwner()鏂规硶锛氫富瑕佹槸鐢ㄤ簬鑾峰彇褰撳墠閿佺殑鎸佹湁鑰咃紝涓€鑸槸绾跨▼瀵硅薄锛屾牴鎹?em>exclusiveCount(getState()) == 0鏉ュ垽鏂紝鏉′欢鎴愮珛灏遍粯璁や负null; 鍚﹀垯锛岄€氳繃AQS鍩虹鍚屾鍣ㄤ腑鐨刧etExclusiveOwnerThread()鏂规硶鏉ヨ幏鍙栥€?/li>
    • getReadLockCount() 鏂规硶锛氱敤浜庤幏鍙栨煇涓嚎绋嬪浜嶳eadLock閿佺殑鏁伴噺锛屼富瑕佹槸缁熻娆℃暟
    • isWriteLocked() 鏂规硶锛氱敤浜庡垽鏂嚎绋嬫槸鍚﹀凡缁忚幏鍙栧苟鎸佹湁WriteLock閿?/li>
    • getWriteHoldCount()鏂规硶锛氱敤浜庤幏鍙栫嚎绋嬪浜嶹riteLock閿佺殑鎸佹湁鎯呭喌锛屼富瑕佹槸缁熻娆℃暟
    • getReadHoldCount() 鏂规硶锛氱敤浜庤幏鍙栫嚎绋嬪浜嶹riteLock閿佺殑鎸佹湁鎯呭喌锛屼富瑕佹槸缁熻娆℃暟
    • isHeldExclusively() 鏂规硶锛氱敤浜庡垽鏂槸鍚︾嫭鍗犳ā寮?/li>
    • unmatchedUnlockException()鏂规硶锛氬皝瑁呬竴涓紓甯稿鐞嗕俊鎭紝涓昏鏄寚瀹欼llegalMonitorStateException

2.2 鍩轰簬Sync鎶借薄绫诲皝瑁呭叡浜姸鎬佸彉閲?/h4>
/** ReentrantReadWriteLock閿?鍩轰簬AQS灏佽鍐呴儴鍚屾鍣?*/
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 6317671515068378041L;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?begin*/
    
    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍏变韩鐘舵€佺Щ鍔ㄤ綅鏁?6 */
    static final int SHARED_SHIFT   = 16;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勭姸鎬佸ぇ灏?/
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣姣忔鍔犻攣鐨勬渶澶ф鏁?/
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍐欓攣鐨勬帺鐮?/
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鏈湴瀛樺偍璇婚攣娆℃暟*/
    private transient ThreadLocalHoldCounter readHolds;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣鐨勭姸鎬佺爜鍊?/
    private transient HoldCounter cachedHoldCounter;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?绾跨▼鍙橀噺*/
    private transient Thread firstReader = null;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?棣栨璇婚攣娆℃暟*/
    private transient int firstReaderHoldCount;

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?end*/
    
    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鏋勯€犳柟娉?/
    Sync() {
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }


    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?璇婚攣鐨勭姸鎬佺爜鍊?/
    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲忓皝瑁?鍐欓攣鐨勭姸鎬佺爜鍊?/
    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲?缁熻璁℃暟鍣?*/
    static final class HoldCounter {
        int count = 0;
        // Use id, not reference, to avoid garbage retention
        final long tid = getThreadId(Thread.currentThread());
    }

    /** ReentrantReadWriteLock閿?鍏辩敤鐘舵€佸彉閲?鏈湴瀛樺偍缁熻鍓湰 */
    static final class ThreadLocalHoldCounter
        extends ThreadLocal<HoldCounter> {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }
    //... 鍏朵粬浠g爜

}
  • 瀹炵幇鏂瑰紡锛?涓昏鏄湪鍐呴儴鐨勫悓姝ュ櫒涓璖ync绫讳腑瀹氫箟HoldCounter绫诲拰ThreadLocalHoldCounter绫诲疄鐜扮殑銆傚叾涓細
    • HoldCounter绫伙細涓昏鏄畾涔変簡涓€涓鏁板櫒count鍜屼竴涓嚎绋嬬紪鍙穞id鍙橀噺锛屽叾涓鏁板櫒count榛樿鍊间负0锛岃€岀嚎绋嬬紪鍙穞id閫氳繃getThreadId(Thread.currentThread())鏂规硶鏉ヨ幏鍙栥€?/li>
    • ThreadLocalHoldCounter绫伙細鍩轰簬ThreadLocal鍜孒oldCounter鏉ユ彁渚涗簡initialValue()鏂规硶锛屼富瑕佹槸瀹炰緥璇濆寲HoldCounter绫汇€?/li>
  • 鍏辩敤鐘舵€佸父閲忥細涓昏鏄湪鍐呴儴鐨勫悓姝ュ櫒涓璖ync绫讳腑瀹氫箟浜嗙浉鍏冲父閲忥紝鍏朵腑锛?
    • SHARED_SHIFT锛?涓昏鐢ㄤ簬鏍囪浣嶇Щ鐨勪綅鏁帮紝榛樿閲囩敤 鏁村瀷16浣?/li>
    • SHARED_UNIT锛氳〃绀鸿閿佸姞閿佹搷浣滄椂姣忔瀵瑰簲鐨勭姸鎬佸€煎ぇ灏忥紝灏?宸︾Щ鍔?6浣嶆濂藉搴旈珮16浣嶇殑1.
    • MAX_COUNT锛氳〃绀鸿閿佽兘鎵ц鍔犻攣鎿嶄綔鐨勬渶澶ф鏁帮紝涓€鑸负16涓簩杩涘埗鐨?
    • EXCLUSIVE_MASK锛氬啓閿佺殑鎺╃爜,涓€鑸负16涓簩杩涘埗鐨?
  • 涓昏鏂规硶锛氫富瑕佹彁渚涗簡缁熻璇诲啓閿佺姸鎬佸€肩殑sharedCount()鏂规硶鍜宔xclusiveCount()鏂规硶锛屽叾涓細
    • sharedCount()鏂规硶锛氳幏鍙栬閿佺殑鐘舵€佺爜鍊硷紝鏍规嵁鐩爣鍙傛暟(targetParam)宸︾Щ16浣嶅嵆鍙緱鍒?/li>
    • exclusiveCount()鏂规硶锛氳幏鍙栧啓閿佺殑鐘舵€佺爜鍊硷紝鏍规嵁鐩爣鍙傛暟(targetParam)鍚屽啓閿佺殑鎺╃爜鍋氶€昏緫涓?&)杩愮畻渚垮彲寰楀埌銆?/li>

涓€鑸潵璇达紝AQS鍩虹鍚屾鍣ㄧ殑鍏变韩鐘舵€佸彉閲忔槸鏁村瀷鐨?2浣嶏紝瑕佸熀浜庝竴涓狝QS鍩虹鍚屾鍣ㄥ疄鐜拌鍐欓攣鐨勫叡浜竴涓叡浜彉閲忋€?lt;br />鍏朵腑锛屾渶鍏钩鐨勬柟寮忚璁℃柟寮忓氨鏄閿佷笌鍐欓攣鍚勮嚜鍗犵敤16浣嶏紝灏辨剰鍛崇潃璇婚攣鍗犵敤鐨勬槸楂?6浣嶏紝鍐欓攣鍗犵敤鐨勬槸浣?6浣嶇殑銆?/p>

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

浣嗘槸锛屽湪鑾峰彇璇诲啓閿佺殑鐘舵€佸€肩殑鏃跺€欙紝杩樹細娑夊強涓€浜涢澶栫殑璁$畻锛岃繖鏍风殑璁捐鏂瑰紡鍙兘浼氶渶瑕佺敤鍒颁綅绉诲拰閫昏緫涓庢搷浣滅瓑銆?/p>

2.3 鍩轰簬Sync鎶借薄绫诲皝瑁匜airSync鍏钩鍚屾鍣?/h4>
/** ReentrantReadWriteLock閿?鍩轰簬Sync鎶借薄绫诲皝瑁匜airSync鍏钩鍚屾鍣?*/
static final class FairSync extends Sync {

    private static final long serialVersionUID = -2274990926593161451L;

    /** ReentrantReadWriteLock閿? 瀹炵幇writerShouldBlock鏂规硶*/
    final boolean writerShouldBlock() {
        return hasQueuedPredecessors();
    }

    /** ReentrantReadWriteLock閿? 瀹炵幇readerShouldBlock鏂规硶*/
    final boolean readerShouldBlock() {
        return hasQueuedPredecessors();
    }
}
  • 瀹炵幇鏂瑰紡锛氬熀浜嶴ync鎶借薄绫诲皝瑁匜airSync鍏钩鍚屾鍣紝琛ㄧず鏀寔鍏钩妯″紡
  • 涓昏鏂规硶锛氫富瑕佸疄鐜板疄鐜皐riterShouldBlock()鏂规硶鍜宺eaderShouldBlock()鏂规硶,鍏朵腑锛?
    • writerShouldBlock()鏂规硶锛氶€氳繃hasQueuedPredecessors()瀹炵幇
    • readerShouldBlock()鏂规硶锛氶€氳繃apparentlyFirstQueuedIsExclusive()瀹炵幇

2.4 鍩轰簬Sync鎶借薄绫诲皝瑁匩onfairSync闈炲叕骞冲悓姝ュ櫒


/** ReentrantReadWriteLock閿?鍩轰簬Sync鎶借薄绫诲皝瑁匜airSync鍏钩鍚屾鍣?*/
static final class NonfairSync extends Sync {
    
    private static final long serialVersionUID = -8159625535654395037L;
    
    /** ReentrantReadWriteLock閿? 瀹炵幇writerShouldBlock鏂规硶*/
    final boolean writerShouldBlock() {
        return false; // writers can always barge
    }

    /** ReentrantReadWriteLock閿? 瀹炵幇readerShouldBlock鏂规硶*/
    final boolean readerShouldBlock() {
        return apparentlyFirstQueuedIsExclusive();
    }
}

  • 瀹炵幇鏂瑰紡锛氬熀浜嶴ync鎶借薄绫诲皝瑁匩onfairSync闈炲叕骞冲悓姝ュ櫒锛岃〃绀烘敮鎸侀潪鍏钩妯″紡
  • 涓昏鏂规硶锛氫富瑕佸疄鐜板疄鐜皐riterShouldBlock()鏂规硶鍜宺eaderShouldBlock()鏂规硶,鍏朵腑锛?
    • writerShouldBlock()鏂规硶锛氶粯璁よ繑鍥瀎alse
    • readerShouldBlock()鏂规硶锛氶€氳繃apparentlyFirstQueuedIsExclusive()瀹炵幇

2.5 鍩轰簬Lock鎺ュ彛瀹炵幇ReadLock璇婚攣鍐呴儴绫?/h4>
/** ReentrantReadWriteLock閿?鍩轰簬Lock鎺ュ彛瀹炵幇ReadLock璇婚攣鍐呴儴绫?/
public static class ReadLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = -5992448646407690164L;

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?鍚屾鍣?*/
    private final Sync sync;

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?鍐呴儴鏋勯€犳柟娉?/
    protected ReadLock(ReentrantReadWriteLock lock) {
        sync = lock.sync;
    }

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?鑾峰彇閿佹柟娉?榛樿鍏变韩妯″紡)*/
    public void lock() {
        sync.acquireShared(1);
    }

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?鑾峰彇閿佹柟娉?鏀寔涓柇鏈哄埗)*/
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?灏濊瘯鑾峰彇閿?涓€鑸ā寮?*/
    public boolean tryLock() {
        return sync.tryReadLock();
    }


    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?灏濊瘯鑾峰彇閿?鏀寔瓒呮椂鏈哄埗)*/
    public boolean tryLock(long timeout, TimeUnit unit)
    throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?閲婃斁閿?/
    public void unlock() {
        sync.releaseShared(1);
    }

    /** ReentrantReadWriteLock閿?ReadLock璇婚攣鍐呴儴绫?鏉′欢鍙橀噺*/
    public Condition newCondition() {
        throw new UnsupportedOperationException();
    }


    public String toString() {
        int r = sync.getReadLockCount();
        return super.toString() +
            "[Read locks = " + r + "]";
    }
}
  • 瀹炵幇鏂瑰紡锛氫富瑕佹槸鍩轰簬Lock鎺ュ彛鏉ュ疄鐜扮殑ReadLock閿侊紝鍚屾椂閫氳繃鏋勯€犳柟娉曟寚瀹氫簡涓€涓唴閮ㄥ悓姝ュ櫒Sync锛屽叾瀵瑰簲鐨勬柟娉曢兘鏄熀浜嶢QS鍩虹鍚屾鍣ㄧ殑鍏变韩妯″紡鏉ュ疄鐜扮殑銆?/li>
  • 鑾峰彇閿佹柟寮忥細涓昏鎻愪緵浜?涓柟娉曟潵瀹炵幇閿佺殑鑾峰彇锛屽叾涓細
    • 鏃犲弬鏁扮殑lock()鏂规硶锛?鑾峰彇閿佺殑涓€鑸ā寮忥紝涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑鐨刟cquireShared(int arg)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄痙oAcquireShared(int arg)鏂规硶
    • 鏃犲弬鏁扮殑lockInterruptibly()鏂规硶锛氳幏鍙栧彲涓柇閿佺殑妯″紡锛屼富瑕佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄤ腑鐨刟cquireSharedInterruptibly(int arg)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄痙oAcquireSharedInterruptibly(int arg)鏂规硶
    • 鏃犲弬鏁扮殑tryLock()鏂规硶锛氬皾璇曡幏鍙朢eadLock閿侊紝涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑鐨則ryReadLock()鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄嚜鏃?compareAndSetState()鏂规硶鐨勫姞鎸丆AS鎿嶄綔鐨勩€?/li>
    • 鏈夊弬鏁扮殑ryLock()鏂规硶锛氬皾璇曡幏鍙朢eadLock閿侊紝鏀寔瓒呮椂鏈哄埗锛屼富瑕佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄤ腑鐨則ryAcquireSharedNanos(int arg, long nanosTimeout)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄湪doAcquireSharedNanos(int arg, long nanosTimeout)鏂规硶锛屼富瑕佹槸鑷棆+shouldParkAfterFailedAcquire()鏂规硶鐨勫姞鎸丆AS鎿嶄綔鐨勩€?/li>
  • 閲婃斁閿佹柟寮忥細涓昏鎻愪緵浜嗕竴涓猽nlock()鏂规硶鏉ュ疄鐜癛eadLock 鐨勯噴鏀撅紝鍏朵腑鏈川鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑鐨剅eleaseShared(int arg) 鏂规硶锛屽叾涓牳蹇冨鐞嗛€昏緫鏄痙oReleaseShared()鐨勬柟娉曪紝鍏舵牳蹇冨鐞嗘槸鑷棆+compareAndSetWaitStatus()鏂规硶鏉ュ姞鎸丆AS鎿嶄綔鐨勩€?/li>

2.6 鍩轰簬Lock鎺ュ彛瀹炵幇WriteLock鍐欓攣鍐呴儴绫?/h4>
/** ReentrantReadWriteLock閿?鍩轰簬Lock鎺ュ彛瀹炵幇WriteLock鍐欓攣鍐呴儴绫?/
public static class WriteLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = -4992448646407690164L;

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鍚屾鍣?/
    private final Sync sync;

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鍐呴儴鏋勯€犳柟娉?/
    protected WriteLock(ReentrantReadWriteLock lock) {
        sync = lock.sync;
    }

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鑾峰彇閿佹柟娉?鐙崰妯″紡)*/
    public void lock() {
        sync.acquire(1);
    }


    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鑾峰彇閿佹柟娉?鍙腑鏂?*/
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鑾峰彇閿佹柟娉?涓€鑸ā寮?*/
    public boolean tryLock( ) {
        return sync.tryWriteLock();
    }

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鑾峰彇閿佹柟娉?鏀寔瓒呮椂鏈哄埗)*/
    public boolean tryLock(long timeout, TimeUnit unit)
    throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }


    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?閲婃斁閿?/
    public void unlock() {
        sync.release(1);
    }



    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鏉′欢鍙橀噺*/
    public Condition newCondition() {
        return sync.newCondition();
    }


    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?鏄惁鐙崰鍒ゆ柇*/
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /** ReentrantReadWriteLock閿?WriteLock鍐欓攣鍐呴儴绫?缁熻鏁伴噺*/
    public int getHoldCount() {
        return sync.getWriteHoldCount();
    }
}
  • 瀹炵幇鏂瑰紡锛氫富瑕佹槸鍩轰簬Lock鎺ュ彛鏉ュ疄鐜扮殑WriteLock閿侊紝鍚屾椂閫氳繃鏋勯€犳柟娉曟寚瀹氫簡涓€涓唴閮ㄥ悓姝ュ櫒Sync锛屽叾瀵瑰簲鐨勬柟娉曢兘鏄熀浜嶢QS鍩虹鍚屾鍣ㄧ殑鐙崰妯″紡鏉ュ疄鐜扮殑銆?/li>
  • 鑾峰彇閿佸紡锛氫富瑕佹彁渚涗簡4涓柟娉曟潵瀹炵幇閿佺殑鑾峰彇锛屽叾涓細
    • 鏃犲弬鏁扮殑lock()鏂规硶锛?鑾峰彇WriteLock閿佺殑涓€鑸ā寮忥紝涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑鐨刟cquire(int arg)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄痑cquireQueued(final Node node, int arg)鏂规硶
    • 鏃犲弬鏁扮殑lockInterruptibly()鏂规硶锛氳幏鍙朩riteLock閿佸彲涓柇閿佺殑妯″紡锛屼富瑕佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄤ腑鐨刟cquireInterruptibly(int arg)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄痙oAcquireInterruptibly(int arg)鏂规硶
    • 鏃犲弬鏁扮殑tryLock()鏂规硶锛氬皾璇曡幏鍙朩riteLock閿侊紝涓昏鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑鐨則ryReadLock()鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄嚜鏃?compareAndSetState()鏂规硶鐨勫姞鎸丆AS鎿嶄綔鐨勩€?/li>
    • 鏈夊弬鏁扮殑ryLock()鏂规硶锛氬皾璇曡幏鍙朩riteLock閿侊紝鏀寔瓒呮椂鏈哄埗锛屼富瑕佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄤ腑鐨則ryAcquireNanos(int arg, long nanosTimeout)鏂规硶鏉ュ疄鐜帮紝鍏舵牳蹇冨鐞嗛€昏緫鏄湪doAcquireNanos(int arg, long nanosTimeout)鏂规硶锛屼富瑕佹槸鑷棆+shouldParkAfterFailedAcquire()鏂规硶鐨勫姞鎸丆AS鎿嶄綔鐨勩€?/li>
  • 閲婃斁閿佹柟寮忥細涓昏鎻愪緵浜嗕竴涓猽nlock()鏂规硶鏉ュ疄鐜癛eadLock 鐨勯噴鏀撅紝鍏朵腑鏈川鏄熀浜嶢QS鍩虹鍚屾鍣ㄤ腑unparkSuccessor(Node node)鏂规硶锛屼富瑕佹槸閫氳繃compareAndSetWaitStatus()鏂规硶鏉ュ姞鎸丆AS鎿嶄綔鐨勩€?/li>

3. 鍏蜂綋瀹炵幇

Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第13张
public class ReentrantReadWriteLock
    implements ReadWriteLock, java.io.Serializable {

        private static final long serialVersionUID = -6992448646407690164L;

        /** ReentrantReadWriteLock閿?鍐呴儴ReadLock绫?*/
        private final ReentrantReadWriteLock.ReadLock readerLock;

        /** ReentrantReadWriteLock閿?鍐呴儴WriteLock绫?*/
        private final ReentrantReadWriteLock.WriteLock writerLock;

        /** ReentrantReadWriteLock閿?鍐呴儴鍚屾鍣?*/
        final Sync sync; 

        /** ReentrantReadWriteLock閿?瀹炰緥鍖朥nsafe鏀寔 */
        private static final sun.misc.Unsafe UNSAFE;

        /** ReentrantReadWriteLock閿?绾跨▼鍋忕Щ閲?*/
        private static final long TID_OFFSET;

        /** ReentrantReadWriteLock閿?鍩轰簬AQS灏佽鍐呴儴鍚屾鍣?*/
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = 6317671515068378041L;

            static final int SHARED_SHIFT   = 16;

            static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

            static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

            static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

            private transient ThreadLocalHoldCounter readHolds;

            private transient HoldCounter cachedHoldCounter;

            private transient Thread firstReader = null;
            private transient int firstReaderHoldCount;

            Sync() {
                readHolds = new ThreadLocalHoldCounter();
                setState(getState()); // ensures visibility of readHolds
            }
            abstract boolean readerShouldBlock();

            abstract boolean writerShouldBlock();

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



        /** ReentrantReadWriteLock閿?鏃犲弬鏁版瀯閫?榛樿闈炲叕骞虫ā寮? */
        public ReentrantReadWriteLock() {
            this(false);
        }

        /** ReentrantReadWriteLock閿?鏈夊弬鏁版瀯閫?鍙€夊叕骞?闈炲叕骞虫ā寮? */
        public ReentrantReadWriteLock(boolean fair) {
            sync = fair new FairSync() : new NonfairSync();
            readerLock = new ReadLock(this);
            writerLock = new WriteLock(this);
        }

        /** ReentrantReadWriteLock閿?鑾峰彇鍐欓攣 */
        public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }      
        /** ReentrantReadWriteLock閿?鑾峰彇璇婚攣 */
        public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public final boolean isFair() {
            return sync instanceof FairSync;
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        protected Thread getOwner() {
            return sync.getOwner();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public int getReadLockCount() {
            return sync.getReadLockCount();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public boolean isWriteLocked() {
            return sync.isWriteLocked();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public boolean isWriteLockedByCurrentThread() {
            return sync.isHeldExclusively();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public int getWriteHoldCount() {
            return sync.getWriteHoldCount();
        }
        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public int getReadHoldCount() {
            return sync.getReadHoldCount();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        protected Collection<Thread> getQueuedWriterThreads() {
            return sync.getExclusiveQueuedThreads();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        protected Collection<Thread> getQueuedReaderThreads() {
            return sync.getSharedQueuedThreads();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public final boolean hasQueuedThreads() {
            return sync.hasQueuedThreads();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public final boolean hasQueuedThread(Thread thread) {
            return sync.isQueued(thread);
        }
        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public final int getQueueLength() {
            return sync.getQueueLength();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        protected Collection<Thread> getQueuedThreads() {
            return sync.getQueuedThreads();
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public boolean hasWaiters(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        protected Collection<Thread> getWaitingThreads(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        public int getWaitQueueLength(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock閿?鑾峰彇绾跨▼鍙橀噺 */
        static final long getThreadId(Thread thread) {
            return UNSAFE.getLongVolatile(thread, TID_OFFSET);
        }

        /** ReentrantReadWriteLock閿?鍙嶅皠鏈哄埗瀹炰緥鍖朥nsafe */
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> tk = Thread.class;
                TID_OFFSET = UNSAFE.objectFieldOffset
                    (tk.getDeclaredField("tid"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
  • 璇诲啓閿佸悓姝ュ櫒锛氫富瑕佹彁渚涗簡2涓瀯閫犳柟娉曟潵瀹炵幇璇诲啓閿佺殑绠$悊锛屽叾涓細
    • 鏃犲弬鏁版瀯閫犳柟娉曪細榛樿闈炲叕骞虫ā寮忥紝涓昏鏄€氳繃this鍏抽敭瀛楁潵鎸囧畾鐨?/li>
    • 鏈夊弬鏁版瀯閫犳柟娉曪細鍙€夊叕骞?闈炲叕骞虫ā寮忥紝渚濇嵁鎸囧畾浼犲叆鍏钩鏍囪fair鏉ュ疄渚嬪寲NonfairSync闈炲叕骞冲悓姝ュ櫒鍜孎airSync鍏钩鍚屾鍣紝鍏朵腑锛屽綋fair=true鏃讹紝鏄叕骞冲钩妯″紡锛涘惁鍒欙紝褰揻air=false鏃朵负闈炲叕骞虫ā寮忋€傚悓鏃讹紝瀹炰緥鍖朢eadLock鍜學riteLock瀵硅薄銆?/li>
  • 璇婚攣涓昏鏂规硶锛氬浜庤閿佺殑鎿嶄綔锛屼竴鑸垜浠彧闇€瑕佸叧娉╮eadLock()鏂规硶鍜岀被浼糶etReadXX() 鏂规硶锛屽叾涓細
    • readLock()鏂规硶锛氫富瑕佺敤浜庤幏鍙栧拰瀹炵幇璇婚攣ReadLock
    • getReadHoldCount() 鏂规硶锛氫富瑕佺敤浜庣粺璁℃煇涓嚎绋嬪浜庤閿佺殑鎸佹湁鎯呭喌
    • getReadLockCount() 鏂规硶锛氫富瑕佺敤浜庣粺璁℃煇涓嚎绋嬪浜庤閿佺殑鑾峰彇鐨勬鏁?/li>
  • 鍐欓攣涓昏鏂规硶锛氬浜庤閿佺殑鎿嶄綔锛屼竴鑸垜浠彧闇€瑕佸叧娉╮eadLock()鏂规硶鍜岀被浼煎寘鍚玿WriteXX() 鏂规硶锛屽叾涓細
    • writeLock() 鏂规硶锛氫富瑕佺敤浜庤幏鍙栧拰瀹炵幇鍐欓攣WriteLock
    • getWriteHoldCount()鏂规硶锛氫富瑕佺敤浜庣粺璁″綋鍓嶇嚎绋嬪浜庡啓閿乄riteLock鐨勬寔鏈夋儏鍐?/li>
    • isWriteLocked()鏂规硶锛氫富瑕佺敤浜庡垽鏂煇涓嚎绋嬪浜庡啓閿乄riteLock鐨勬槸鍚﹀姞閿?/li>
    • isWriteLockedByCurrentThread() 鏂规硶锛氫富瑕佺敤浜庡垽鏂綋鍓嶇嚎绋嬪浜庡啓閿乄riteLock鐨勬槸鍚﹀姞閿?/li>
  • 鏉′欢闃熷垪鎿嶄綔鏂规硶锛氳繕鎻愪緵浜嗕竴绯诲垪鐨勫浜庢潯浠跺彉閲忛槦鍒楁搷浣滄柟娉曪紝鍏朵腑锛?
    • getQueuedWriterThreads() 鏂规硶锛氫富瑕佺敤浜庤幏鍙栫嚎绋嬬瓑寰呰幏鍙栧啓閿乄riteLock鐨勬儏鍐?/li>
    • getQueuedReaderThreads() 鏂规硶锛氫富瑕佺敤浜庤幏鍙栫嚎绋嬬瓑寰呰幏鍙栬閿丷eadLock鐨勬儏鍐?/li>
    • getQueuedThreads()鏂规硶锛氫富瑕佺敤浜庤幏鍙栫嚎绋嬬瓑寰呰幏鍙栬閿丷eadLock鍜屽啓閿乄riteLock鐨勬儏鍐?/li>
    • getQueueLength() 鏂规硶锛氫富瑕佺敤浜庤幏鍙栫嚎绋嬬瓑寰呰幏鍙栬閿丷eadLock鍜屽啓閿乄riteLock鐨勪釜鏁?/li>
  • 绛夊緟闃熷垪鎿嶄綔鏂规硶锛?杩樻彁渚涗簡涓€绯诲垪鐨勫浜庣瓑寰呴槦鍒楁搷浣滄柟娉曪紝鍏朵腑锛?
    • getWaitingThreads() 鏂规硶锛氫富瑕佷緷鎹瓹ondition鏉ョ敤浜庤幏鍙栫瓑寰呴槦鍒椾腑鎵€鏈夌殑绾跨▼鐨勫璞?/li>
    • getWaitQueueLength() 鏂规硶锛氫富瑕佷緷鎹瓹ondition鏉ョ敤浜庤幏鍙栫瓑寰呴槦鍒椾腑鎵€鏈夌殑绾跨▼瀵逛簬鍐欓攣WriteLock鐨勭浉鍏崇殑涓暟
  • 鍏朵粬鏂规硶锛氶櫎姝や箣澶栵紝杩樻彁渚涗簡涓€浜涢槦鍒楁搷浣滅殑甯歌鏂规硶锛屽叾涓細
    • hasQueuedThread() 鏂规硶锛氫富瑕佷緷鎹崟涓猅hread瀵硅薄鐢ㄤ簬鑾峰彇绾跨▼鏄惁鏈夎幏鍙栬閿丷eadLock鍜屽啓閿乄riteLock鐨勬儏鍐?/li>
    • hasQueuedThreads() 鏂规硶锛氫富瑕佺敤浜庤幏鍙栧涓嚎绋嬫槸鍚︽湁鑾峰彇璇婚攣ReadLock鍜屽啓閿乄riteLock鐨勬儏鍐?/li>
    • hasWaiters()鏂规硶锛氫富瑕佷緷鎹瓹ondition鏉ョ敤浜庡垽鏂瓑寰呴槦鍒椾腑鎵€鏈夌殑绾跨▼瀵逛簬鍐欓攣WriteLock鐨勭浉鍏虫儏鍐?/li>
    • isFair() 鏂规硶锛氱敤浜庡垽鏂槸鍚﹀叕骞虫ā寮?/li>
    • getThreadId()鏂规硶锛氳幏鍙栫嚎绋嬬紪鍙稩D锛屼富瑕佹槸閫氳繃鎸囧畾UNSAFE.getLongVolatile(thread, TID_OFFSET)瀹炵幇銆?/li>

<br />缁间笂鎵€杩帮紝ReentrantReadWriteLock閿佹槸鍩轰簬AQS鍩虹鍚屾鍣ㄧ殑鍏变韩妯″紡鍜岀嫭浜ā寮忓叡鍚屽鍖栫殑浜х墿锛屾敮鎸佸叕骞?闈炲叕骞虫ā寮忥紝鍏朵腑鐨凴eadLock鍜學riteLock鏄熀浜庡悓涓€涓狝QS鍩虹鍚屾鍣ㄦ潵瀹炵幇锛岀淮鎶や簡鍏辩敤鐘舵€佸彉閲忔満鍒躲€?/p>

鍐欏湪鏈€鍚?/h2>
Java并发编程解析 - 基于JDK源码解析Java领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二),第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/39y1923765.html

相关文章: