1. 程式人生 > >讀者寫者問題

讀者寫者問題

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 // 最後一個讀者退出, 釋放共享區操作權限
12
if (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 writer
3 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 }

讀者寫者問題