哲學家問題對於多個競爭進程互斥地訪問有限資源(如I/O裝置)這一類問題的建模十分有用。另一個著名的問題是讀者-寫者問題,它為資料庫訪問建立了一個模型。例如,設想一個飛機定票系統,其中有許多競爭的進程試圖讀寫其中的資料。多個進程同時讀是可以接受的,但如果一個進程正在更新資料庫,則所有其他進程都不能訪問資料庫,即使讀操作也不行。這裡的問題是:如何對讀者和寫者進行編程?圖2-19給出了一種解法。
typedef int semaphore;semaphore mutex=1; /* 控制對RC的訪問 */semaphore db=1; /* 控制對資料庫的訪問 */int rc=0; /* 正在讀或想要讀的進程數 */void reader(void){while(TRUE){ /* 無限迴圈 */down(&mutex);/* 排斥對RC的訪問*/rc = rc+1; /*又多了一個讀者*/if(rc == 1)down(&db);/*如果這是第一個讀者,那麼......*/up(&mutex); /*恢複對RC的訪問*/read_data_base(); /*訪問資料*/down(&mutex); /*排斥對RC的訪問*/rc = rc -1; /*讀者又少了一個*/if(rc==0)up(&db);/*如果這是最後一個讀者,那麼......*/use_data_read();/*非臨界區操作*/}}void writer(void){while(TRUE){think_up_data();/*非臨界區操作*/down(&db); /*排斥訪問*/write_data_base(); /*修改資料*/up(&db); /*恢複訪問*/}}圖2-19 一個讀者與作者問題的解決方案
第一個讀者對訊號量db執行DOWN。隨後的讀者只是遞增一個計數器rc。當讀者離開時,它們遞減這個計數器,而最後一個讀者則對db執行UP,這樣就允許一個阻塞的寫者可以訪問資料庫。
設想當一個讀者在使用資料庫時,另一個讀者也來訪問資料庫,由於同時允許多個讀者同時進行讀操作,所以第二個讀者也被允許進入,同理第三個及隨後更多的讀者都被允許進入。
現在假設一個寫者到來,由於寫操作是排他的,所以它不能訪問資料庫,而是被掛起。隨後其他的讀者到來,這樣只要有一個讀者活躍,隨後而來的讀者都被允許訪問資料庫。這樣的結果是只要有讀者陸續到來,它們一來就被允許進入,而寫者將一直被掛起直到沒有一個讀者為止。假如每2秒鐘來一個讀者,而其操作時間為5秒鐘,則寫者將永遠不能訪問資料庫,或者我們說寫者發生了饑餓現象。這就是讀者優先的解法。