程序同步互斥——不死鎖哲學家問題
一、問題分析
二、概要設計
(1)利用程序併發執行原理,採用奇數號哲學家先拿左叉子,偶數號哲學家先拿右叉子的演算法解決哲學家就餐問題。
(2)利用java中Swing技術將哲學家就餐的活動過程用可檢視形化介面表示出來
三、程式碼實現:
Philosopher類
/** * Philosopher類模擬哲學家的就餐活動過程 * @author Administrator */ public class Philosopher extends JLabel implements Runnable{ /** * 哲學家編號 */ private int id = 0; /** * suspend = true 執行緒暫停 */ private boolean suspend = false; public Philosopher(int id, Semaphore leftFork, Semaphore rightFork, //哲學家初始化設計,統一設計哲學家的初始狀態為思考 } /** * 若suspend設定為false,繼續運行當前程序 */ public void setSuspend(boolean suspend) { //使用Object的notifyAll()方法來喚醒當前執行緒 } /** * 狀態轉為思考 */ private void think() { //返回資訊給使用者,並將當前影象設為思考的影象。 } /** * 狀態轉為就餐 */ private void eat() { //返回資訊給使用者,並將當前影象設為思考的影象。 } /** * 申請右叉子 */ private void waitRightFork(){ //使用Semaphore.acquire()向計數訊號量獲得一個許可,來模擬申請右 //叉子. //返回相關狀態資訊給使用者 } /** * 申請左叉子 */ private void waitLeftFork() throws InterruptedException { //使用Semaphore.acquire()向計數訊號量獲得一個許可,來模擬申請左 //叉子. //返回相關狀態資訊給使用者 } /** * 釋放所有叉子 */ private void releaseFork() { //使用Semaphore.release() 釋放一個許可,將其返回給訊號量。來模 //擬釋放左右叉子. //返回相關狀態資訊給使用者 } /** * 判斷是否要暫停當前程序 */ private void checkSuspend() { //Object的wait()方法來暫停當前執行緒 } /** * 奇數號哲學家先拿左叉子,偶數號哲學家先拿右叉子 */ public void run() { try{ while(true) { //設狀態為思考 if(id % 2 == 1) { //奇數號哲學家先拿左叉子 } else { //偶數號哲學家先拿右叉子 } //設狀態為吃東西 //釋放所有叉子 } } } }
四、除錯分析
(1)除錯和設計過程中遇到的問題與解決
1) 問題:實現同步互斥時,只用了簡單的執行緒同步方法,無法實現互斥
解決方法:使用java中Semaphore類來建立訊號量,並通過 Semaphore.acquire() 和Semaphore.release()來模擬叉子的釋放和申請
2) 問題:本程式為方便使用者觀看哲學家們就餐的過程,在程式中添加了一個控制 按鈕來控制程式的執行和暫停,但java中的Thread.stop()被認為執行緒不安全, 所以不能使用該方法來控制執行緒.
解決方法:Object的wait()和notifyAll()方法。使用這兩個方法讓執行緒暫停,並且還能恢復,向哲學家類中新增一個標誌變數suspend方法,每個狀態發生改變時,檢查標誌變數suspend的值來決定是否要暫停當前執行緒,從而主程式可以通過改變哲學家類中的suspend的值,來控制是否暫停當前哲學家程序。
3) 問題:釋放叉子和改變叉子的顯示狀態問題,如果先釋放叉子,然後再改變叉子狀態就會出現以下問題。
雖然叉子的訊號量已被申請出去,但使用者看到的卻是叉子還存在的狀態。
解決方法:先顯示叉子,再釋放叉子的訊號量。
五、使用者使用說明
本程式利用程序併發執行的原理,設計合適的演算法來解決哲學家就餐問題,並把哲學家們的活動過程用文字和視覺化影象顯示出來。所以在程式中只用一個用來控制程式暫停和執行的可操作按鈕。
六、測試與執行結果
本程式為模擬哲學家就餐的活動過程,如下圖所示5位哲學家和5把叉子,哲學家們的初始狀態都為“思考”,在程式介面中,順時針方向為左,逆時針方向為右
每個哲學家有3個狀態:“思考”,“飢餓”和“吃麵”,每個哲學家程序通過訊號量來實現同步互斥。為了方便使用者觀看,使用