爲了熟悉哈斯克爾STM,我寫了下面的解決哲學家就餐問題:以下解決方案「Dining Philosophers」有什麼問題?
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import System.Random
type Fork = TVar Bool
type StringBuffer = TChan String
philosopherNames :: [String]
philosopherNames = map show ([1..] :: [Int])
logThinking :: String -> StringBuffer -> STM()
logThinking name buffer = writeTChan buffer $ name ++ " is thinking..."
logEating :: String -> StringBuffer -> STM()
logEating name buffer = writeTChan buffer $ name ++ " is eating..."
firstLogEntry :: StringBuffer -> STM String
firstLogEntry buffer = do empty <- isEmptyTChan buffer
if empty then retry
else readTChan buffer
takeForks :: Fork -> Fork -> STM()
takeForks left right = do leftUsed <- readTVar left
rightUsed <- readTVar right
if leftUsed || rightUsed
then retry
else do writeTVar left True
writeTVar right True
putForks :: Fork -> Fork -> STM()
putForks left right = do writeTVar left False
writeTVar right False
philosopher :: String -> StringBuffer -> Fork -> Fork -> IO()
philosopher name out left right = do atomically $ logThinking name out
randomDelay
atomically $ takeForks left right
atomically $ logEating name out
randomDelay
atomically $ putForks left right
randomDelay :: IO()
randomDelay = do delay <- getStdRandom(randomR (1,3))
threadDelay (delay * 1000000)
main :: IO()
main = do let n = 8
forks <- replicateM n $ newTVarIO False
buffer <- newTChanIO
forM_ [0 .. n - 1] $ \i ->
do let left = forks !! i
right = forks !! ((i + 1) `mod` n)
name = philosopherNames !! i
forkIO $ forever $ philosopher name buffer left right
forever $ do str <- atomically $ firstLogEntry buffer
putStrLn str
當我編譯和運行我的解決方案,似乎不存在明顯的併發問題:每個哲學家會最終吃掉,沒有哲學家似乎被青睞。但是,如果我從philosopher
刪除randomDelay
聲明,編譯和運行,我的程序的輸出如下所示:
1 is thinking...
1 is eating...
1 is thinking...
1 is eating...
2 is thinking...
2 is eating...
2 is thinking...
2 is eating...
2 is thinking...
2 is eating...
2 is thinking...
About 2500 lines later...
2 is thinking...
2 is eating...
2 is thinking...
3 is thinking...
3 is eating...
3 is thinking...
3 is eating...
And so on...
什麼在這種情況下是怎麼回事?
如果這是家庭作業,請添加作業選項卡。 – Gray
這不是作業,我在真實世界的Haskell上看過STM,我正在努力熟悉它。 – Alexandros
與我的設置(Debian 6 Testing,ghc 7.4.1,runhaskell/ghc -O2 --make philosophers.hs)我認爲我沒有問題 - 哲學家1.8正在進食和思考每個輪到它。你的ghc版本是什麼,你正在編譯或使用ghci嗎? – epsilonhalbe