程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 關於讀寫鎖算法的Java實現及思考

關於讀寫鎖算法的Java實現及思考

編輯:關於JAVA

問題背景:多個線程對一個共享的資源進行讀寫訪問。寫線程之間需要互斥,讀線程跟寫線程需要互斥,讀線程之間不用互斥。

早些時候聽張sir的課,講述java5中增強並發的功能。用Java.util.concurrent.locks中ReadWriteLock 可以輕松解決讀寫鎖問題。我在思考如果沒有ReadWriteLock,單靠synchronized可以怎樣做呢? 的確,比較麻煩。

1.結合張sir傳授的面向對象的設計思想,首先設計一個業務類Business作為共享資源,封裝write跟read方法。

2.因為write必定互斥,所以直接定義synchronized。

3.read之間不要互斥 所以read 不能直接定義synchronized的 但是 write跟read 需要互斥 如何控制 我想到的一個方法是在read裡 加入synchronized(this){} 同時定義readThreads計數器作為信號量 我試想下會出現下面幾種情況:

read[m]表示某個線程的read方法 。

write[n] 同上

1>read[m]中執行到synchronized(this){readThreads++;}時 write[n]來了 write[n] 會被自身的synchronized阻塞。

2>read[m]在do something(此時無鎖)時 write[n] 來了 因為 readThreads!=0 而被迫wait。

3> 每次read[m]結束時 wait中的write[n]會被notify 但如果發現還有其他的read的話 write[n] 只能無奈地再次wait。

4>當readThreads==0並且調用notifyAll 時 read[m] 和 write[n] 會競爭cpu 如果write[n]再次落敗,則會出現1>或3> ; 如果成了,則如下:

5> 如果write[n] wait中醒來占鎖,read[m]被阻塞synchronized(this){readThreads++;}之上。

6>如果被阻塞的write[n]占鎖,read[m]被阻塞synchronized(this){readThreads++;}之上。

從以上看來read 和 write 是互斥的。

4.實現細節如下:<如有錯誤歡迎指出交流>

  1. package communication;
  2. import Java.util.Random;
  3. public class ReadWriteLockTest {
  4. public static void main(String[] args){
  5. final Business business = new Business();
  6. //啟動4線程 2讀 2寫
  7. for(int i=1;i<=2;i++){
  8. new Thread(new Runnable(){
  9. public void run() {
  10. for(int j=1;j<1000;j++){
  11. business.read();
  12. try {
  13. Thread.sleep(900);
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19. }).start();
  20. new Thread(new Runnable(){
  21. public void run() {
  22. Random r = new Random();
  23. for(int j=1;j<1000;j++){
  24. int i = r.nextInt(100);
  25. business.write(i);
  26. try {
  27. Thread.sleep(1000);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }
  33. }).start();
  34. }
  35. }
  36. }
  37. //封裝的業務類
  38. class Business{
  39. private int data=0; //共享資源屬性
  40. private int readThreads = 0; //讀線程數
  41. //private boolean isWriting = false;
  42. //是否執行寫 後來發現不需要 當write搶占鎖時 所有的read 都被擋在synchronized (this){}之上 無機會執行wait
  43. public void read(){
  44. synchronized (this) {
  45. /*while(isWriting){
  46. try {
  47. this.wait();
  48. } catch (InterruptedException e) {
  49. // TODO Auto-generated catch block
  50. e.printStackTrace();
  51. }
  52. }*/
  53. //readThreads不被鎖的話 會出現read和write不互斥的小概率事件 導致線程不安全
  54. readThreads++;
  55. }
  56. System.out.println(Thread.currentThread().getName()+" read begin");
  57. System.out.println(Thread.currentThread().getName()+" read:"+data);
  58. System.out.println(Thread.currentThread().getName()+" read finish");
  59. synchronized (this) {
  60. readThreads--;
  61. this.notifyAll();
  62. }
  63. }
  64. public synchronized void write(int i){
  65. while(readThreads != 0){//當read 正處於do something狀態時 來個write 那就只有等等先了
  66. try {
  67. this.wait();
  68. } catch (InterruptedException e) {
  69. e.printStackTrace();
  70. }
  71. }
  72. //isWriting = true;
  73. System.out.println(Thread.currentThread().getName()+" write start");
  74. data = i;
  75. System.out.println(Thread.currentThread().getName()+" write:"+i);
  76. System.out.println(Thread.currentThread().getName()+" write over");
  77. //isWriting = false;
  78. this.notifyAll();
  79. }
  80. }

思考中:

5.當讀頻繁時 readThreads會長時間!= 0 寫線程會餓死 這個可以如何解決?

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