程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java的ReadWriteLock實現機制解析(2)

Java的ReadWriteLock實現機制解析(2)

編輯:關於JAVA

1.3 EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock

上一篇說到了WriterPreferenceReadWriteLock,這一篇說一下ReentrantWriterPreferenceReadWriteLock。

顧名思義,該類實現的是可重入的的WriterPreferenceReadWriteLock。允許readers和writers在各自線程裡反復獲得讀或寫的鎖。這種方法主要用在

該類是WriterPreferenceReadWriteLock的子類,與父類大體流程一致,但是startWrite,startRead ,allowReader ,endRead和endWrite被重寫,下面逐一解釋。

先看看新添加的成員變量

Java代碼

  1. /**在activeWriter線程裡,有多少次write鎖的控制權被獲取**/
  2. protected long writeHolds_ = 0;
  3. /**存放的每個reader線程共申請獲得多少次讀控制,key值是thread對象,value是次數**/
  4. protected HashMap readers_ = new HashMap();
  5. /*一個int的常量緩存*/
  6. protected static final Integer IONE = new Integer(1);

再來看看Reader部分的重寫函數

Java代碼

  1. protected boolean allowReader() {
  2. //與父類的變化在於,activeWriter_ == Thread.currentThread(),
  3. //也就是說當本線程已經獲得寫控制的時候,返回true
  4. return (activeWriter_ == null && waitingWriters_ == 0) ||
  5. activeWriter_ == Thread.currentThread();
  6. }
  7. protected synchronized boolean startRead() {
  8. Thread t = Thread.currentThread();
  9. //查看本線程是否已經獲得讀控制
  10. Object c = readers_.get(t);
  11. if (c != null) { // already held -- just increment hold count
  12. //計數+1
  13. readers_.put(t, new Integer(((Integer)(c)).intValue()+1));
  14. ++activeReaders_;
  15. return true;
  16. }
  17. //調用allowReader
  18. else if (allowReader()) {
  19. //將本線程獲鎖次數紀錄在readers_這個map裡
  20. readers_.put(t, IONE);
  21. ++activeReaders_;
  22. return true;
  23. }
  24. else
  25. return false;
  26. }
  27. protected synchronized Signaller endRead() {
  28. Thread t = Thread.currentThread();
  29. Object c = readers_.get(t);
  30. if (c == null)
  31. throw new IllegalStateException();
  32. --activeReaders_;
  33. if (c != IONE) { // 多於一個讀線程有控制權,more than one hold; 計數遞減
  34. int h = ((Integer)(c)).intValue()-1;
  35. Integer ih = (h == 1)? IONE : new Integer(h);
  36. readers_.put(t, ih);
  37. return null;
  38. }
  39. else {
  40. readers_.remove(t);
  41. if (writeHolds_ > 0) // 本線程還有寫鎖在占用控制權
  42. return null;
  43. //其余與父類實現一樣
  44. else if (activeReaders_ == 0 && waitingWriters_ > 0)
  45. return writerLock_;
  46. else
  47. return null;
  48. }
  49. }

Reader部分相對於父類的變化在於

* 每個reader試圖競爭控制權時,都會將本線程句柄與activeWriter進行比較,相同則認為是可以重入。

* 每個reader線程都在readers_的map裡有一個計數器,判斷當前有多少次獲得reader鎖權,釋放的時候,只有當計數器為0時才通知其他寫線程結束wait。

接著看看Writer部分的重寫函數

Java代碼

  1. protected synchronized boolean startWrite() {
  2. if (activeWriter_ == Thread.currentThread()) { // 反復重入
  3. ++writeHolds_;
  4. return true;
  5. }
  6. else if (writeHolds_ == 0) {
  7. //如果沒有人在讀(activeReaders_==0)和,或者在讀的線程和本線程一樣,並且readers裡沒有其他線程
  8. if (activeReaders_ == 0 ||
  9. (readers_.size() == 1 &&
  10. readers_.get(Thread.currentThread()) != null)) {
  11. //如果本線程在讀中,則也可以進入writeLock
  12. activeWriter_ = Thread.currentThread();
  13. writeHolds_ = 1;
  14. return true;
  15. }
  16. else
  17. return false;
  18. }
  19. else
  20. return false;
  21. }
  22. protected synchronized Signaller endWrite() {
  23. --writeHolds_;
  24. if (writeHolds_ > 0)
  25. //這是主要與父類不一樣的地方,寫鎖計數標示仍然有寫鎖沒有被釋放
  26. return null;
  27. else {
  28. //與父類一致
  29. activeWriter_ = null;
  30. if (waitingReaders_ > 0 && allowReader())
  31. return readerLock_;
  32. else if (waitingWriters_ > 0)
  33. return writerLock_;
  34. else
  35. return null;
  36. }
  37. }

Writer主要與父類不同的地方是

* 通過writeHolds來記錄本線程獲得鎖的次數,以便在release時正確調用通知機制

* 通過當前線程和activeWriter線程比較來實現重入

1.3 EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock

ReaderPreferenceReadWriteLock類和父類唯一不同就是allowReader方法

Java代碼

  1. protected boolean allowReader() {
  2. //只要沒有寫,就允許讀
  3. return activeWriter_ == null;
  4. }

這個類在大多數場景下都不太實用,多數人主要還是使用writer優先鎖。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved