讀者寫者問題
阿新 • • 發佈:2018-11-18
spa ++ 存在 獲取 base 在操作 變量 tor while
1. 讀者寫者問題
讀者優先: 只要有一個Reader處於活動狀態, 那麽後面來的Reader都會被接納. 若Reader源源不斷, 那麽Writer就會一直處於阻塞狀態, 即寫者被餓死.
寫者優先: 一旦Writer就緒, 就會先執行Writer, 寫者優先級高於讀者, 若Writer源源不斷, 那麽Reader就會一直處於阻塞狀態, 即讀者被餓死.
2. 信號量 - 讀者優先
數據結構
1 data // 共享數據 2 CountMutex = 1 // 保證Rcount互斥 3 WriterMutex = 1 // 讀者寫者互斥 4 Rcount = 0 // 讀者數量
寫者
1 sem_wait(WriterMutex); 2 3 write data; 4 5 sem_post(WriterMutex);
讀者
1 sem_wait(Rcount); 2 // 第一個讀者進入, 獲取共享區操作權限 3 if (Rcount == 0) sem_wait(WriterMutex); 4 ++Rcount; 5 sem_post(Rcount); 6 7 read data; 8 9 sem_wait(Rcount); 10 --Rcount; 11 // 最後一個讀者退出, 釋放共享區操作權限 12if (Rcount == 0) sem_post(WriterMutex); 13 sem_post(Rcount);
3. 管程 - 寫者優先
數據結構
AR = 0 // 正在讀的讀者 AW = 0 // 正在寫的寫者 WR = 0 // 正在等待的讀者 WW = 0 // 正在等待的寫者 Condition okToRead // 條件變量: 可讀 Condition okToWrite // 條件變量: 可寫 Lock lock // 線程互斥鎖
讀者
1 public Database::Read() { 2 // wait until no writer3 StartRead(); 4 5 read database; 6 7 // check out - wake up waiting writers 8 DoneRead(); 9 } 10 11 private Database::StartRead() { 12 lock.Acquire(); 13 // 若存在正在寫或正在等待的寫者, 就將讀者加入等待隊列中 14 while ((AW + WW) > 0) { 15 WR++; 16 okToRead.wait(&lock); // 睡眠, 被喚醒後從這裏開始執行 17 WR--; 18 } 19 // 允許同時存在多個讀者 20 AR++; 21 lock.Release(); 22 } 23 24 private Database::DoneRead() { 25 lock.Acquire(); 26 AR--; 27 // 若最後一個正在讀的讀者退出且有寫者在排隊, 那麽就喚醒一個寫者 28 if (AR == 0 && WW > 0) { 29 okToWrite.signal(); // 喚醒一個寫者 30 } 31 lock.Release(); 32 }
寫者
1 public Database::Write() { 2 // wait until no readers or writers 3 StartWrite(); 4 5 write database; 6 7 // check out - wake up waiting writers or readers 8 DoneWrite(); 9 } 10 11 private Database::StartWrite() { 12 lock.Acquire(); 13 // 若存在正在操作數據庫的對象, 就等待 14 // 由於 AW 也包含, 所以一次只允許一個讀者操作數據庫 15 while ((AW + AR) > 0) { 16 WW++; 17 okToWrite.wait(&lock); 18 WW-- 19 } 20 AW++; 21 lock.Release(); 22 } 23 24 private Database::DoneWrite() { 25 lock.Acquire(); 26 AW--; 27 // 若存在正在等待的寫者, 則喚醒隨機一個 28 if (WW > 0) { // 條件1 29 okToWrite.signal(); 30 } 31 // 若條件1不滿足且存在正在等待的讀者, 則喚醒全部正在等待的讀者 32 else if (WR > 0) { 33 okToWrite.broadcast(); 34 } 35 lock.Release(); 36 }
讀者寫者問題