The Little Book of Semaphores 訊號量小書 第七章 不太遙遠的經典問題 7.6 餐廳問題
第七章 不太遙遠的經典問題
7.6 餐廳問題(Dining Hall problem)
這個問題是由Jon Pollack在Olin College的同步課程中編寫的。
學生們在餐廳裡用餐(dine),然後離開(leave)。 在呼叫dine之後,呼叫leave之前,學生被認為“準備離開”。
適用於學生的同步約束是,為了保持社會溫和的錯覺,學生永遠不能獨自坐在桌子旁。 如果在完成用餐之前一同用餐的其他所有人都已離開,則該學生被認為是獨自坐著。
思考:編寫強制執行此約束的程式碼。
7.6.1 餐廳問題提示
eating和readyToLeave是由互斥鎖保護的計數器,因此這是通常的記分板模式。
如果學生準備離開,但另一名學生將獨自留在桌旁,她等待okToLeave,直到另一名學生改變情況併發出訊號。
7.6.2 餐廳問題方案
如果你分析這些約束條件,你會發現學生只有一種情況需要等待,如果有一個學生正在吃飯,另一個學生想要離開。 但有兩種方法可以擺脫這種情況:有另一名學生來吃飯,或者正在就餐的學生要吃完了。
在任何一種情況下,向等待學生髮出訊號的學生都會更新計數器,因此等待的學生不必返回互斥鎖。 這是“我會為你做的”模式的另一個例子。
當學生進入餐廳時,如果她看到一個學生正在吃飯,而另一個正在等待離開,她就會讓等待者擺脫困境,併為他遞減readyToLeave。
用餐後,學生檢查三種情況:
•如果只剩下一名學生,則即將離開的學生必須放棄互斥並等待。
•如果即將離開的學生髮現有人在等她,她會向他發出訊號併為他們更新計數器。
•否則,她只是遞減readyToLeave並離開。
7.6.3 擴充套件的餐廳問題
如果我們再增加一步,餐廳問題會變得更具挑戰性。 當學生來吃午餐時,他們會呼叫getFood,dine和leave。 在呼叫getFood之後和呼叫dine之前,學生被認為是“準備吃飯”。 同樣,在呼叫用餐後,學生被認為“準備離開”。
適用同樣的同步約束:學生永遠不能獨自坐在桌旁。如果有以下情況之一的話,學生被認為是獨自坐著:
•當桌上沒有其他人準備吃時,她呼叫dine
•在她完成用餐之前,所有已經呼叫過dine的人都呼叫了leave。
思考:編寫強制執行這些約束的程式碼。
7.6.4 擴充套件的餐廳問題提示
以下是我在解決方案中使用的變數:
readyToEat,eating和readyToLeave是計數器,全部受互斥鎖保護。
如果學生處於無法繼續的狀態,她會等待okToSit或okToLeave,直到另一名學生改變情況併發出訊號。
我還使用了名為hasMutex的執行緒內變數來幫助跟蹤執行緒是否持有互斥鎖。
7.6.5 擴充套件的餐廳問題方案
同樣,如果我們分析這些約束,我們就會發現只有一種情況,即如果沒有人吃飯,也沒有其他人準備吃飯,則準備吃飯的學生必須等待。 唯一的出路就是,有其他準備吃的人來了。
同樣,如果我們分析這些約束,我們就會意識到,只有一種情況,即準備就餐的學生必須等待,如果沒有人吃飯,也沒有其他人準備就餐。
與前面的解決方案一樣,我使用了“我會為你做的”模式,這樣等待的學生就不必返回互斥物件。
這個解決方案與前一個解決方案的主要區別在於,到達空桌的第一個學生必須等待,而第二個學生允許兩人繼續進行。 無論是哪種情況,我們都無需檢查等待離開的學生,因為沒有人可以離開一張空桌子!