1. 程式人生 > >The Little Book of Semaphores 訊號量小書 第七章 不太遙遠的經典問題 7.6 餐廳問題

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 擴充套件的餐廳問題方案

同樣,如果我們分析這些約束,我們就會發現只有一種情況,即如果沒有人吃飯,也沒有其他人準備吃飯,則準備吃飯的學生必須等待。 唯一的出路就是,有其他準備吃的人來了。

同樣,如果我們分析這些約束,我們就會意識到,只有一種情況,即準備就餐的學生必須等待,如果沒有人吃飯,也沒有其他人準備就餐。

與前面的解決方案一樣,我使用了“我會為你做的”模式,這樣等待的學生就不必返回互斥物件。

這個解決方案與前一個解決方案的主要區別在於,到達空桌的第一個學生必須等待,而第二個學生允許兩人繼續進行。 無論是哪種情況,我們都無需檢查等待離開的學生,因為沒有人可以離開一張空桌子!