2012-08-30 15 views
5

आदेश हास्केल में एसटीएम से परिचित पाने के लिए, मैं भोजन दार्शनिकों समस्या के लिए निम्न समाधान लिखा है:"डाइनिंग फिलॉसॉफर्स" के लिए निम्नलिखित समाधान में क्या गलत है?

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... 

इस मामले में क्या हो रहा है?

+0

यदि यह होमवर्क है, तो कृपया होमवर्क टैब जोड़ें। – Gray

+0

यह होमवर्क नहीं है, मैंने रियल वर्ल्ड हास्केल में एसटीएम के बारे में पढ़ा है और मैं इसके साथ खुद को परिचित करने की कोशिश कर रहा हूं। – Alexandros

+0

मेरे सेटअप के साथ (डेबियन 6 टेस्टिंग, ghc 7.4.1, runhaskell/ghc -O2 --make philosophers.hs) मुझे नहीं लगता कि मुझे कोई समस्या है - दार्शनिक 1 ..8 खाने और सोचने के बाद प्रत्येक को सोच रहे हैं। आपका ghc संस्करण क्या है और क्या आप ghci संकलन या प्रयोग कर रहे हैं? – epsilonhalbe

उत्तर

5

आप +RTS -N (या +RTS -Nk जहां k धागे की संख्या है के साथ इसे चलाने थ्रेडेड क्रम के साथ यह संकलन करने की जरूरत और rtsopts सक्षम है, और। कि के साथ, मैं उत्पादन की तरह

8 is eating... 
6 is eating... 
4 is thinking... 
6 is thinking... 
4 is eating... 
7 is eating... 
8 is thinking... 
4 is thinking... 
7 is thinking... 
8 is eating... 
4 is eating... 
4 is thinking... 
4 is eating... 
6 is eating... 
4 is thinking... 

बिंदु है मिल कि किसी अन्य दार्शनिक के लिए सोचने/खाने के लिए, यदि आपके स्वभाव पर कई हार्डवेयर धागे नहीं हैं तो एक संदर्भ स्विच होना चाहिए। ऐसा संदर्भ स्विच अक्सर यहां नहीं होता है, जहां अधिक आवंटन नहीं किया जाता है, इसलिए प्रत्येक दार्शनिक के पास होता है अगले व्यक्ति की बारी आने से पहले बहुत सोचने और खाने के लिए बहुत समय लगता है।

आपके स्वभाव पर पर्याप्त धागे के साथ, सभी दार्शनिक एक साथ कांटे तक पहुंचने की कोशिश कर सकते हैं।

+0

'+ आरटीएस-एन 9' के साथ (प्रत्येक दार्शनिक के लिए 8 धागे और मुख्य थ्रेड के लिए 1, जो' stdout' को लिखते हैं), ऐसा लगता है कि दो दार्शनिक एक निश्चित समय के लिए सीपीयू एकाधिकार कर रहे हैं। – Alexandros

+4

आप कितने कोर हैं? आपके पास हार्डवेयर क्षमताओं की तुलना में एक ही समय में चलने वाले अधिक थ्रेड नहीं हो सकते हैं, इसलिए यदि आपके पास दोहरी कोर मशीन है, तो दो से अधिक दार्शनिक किसी भी समय कांटे के लिए प्रतिस्पर्धा नहीं कर सकते हैं। –

+0

ओएस धागे की संख्या के बजाय उपयोग करने के लिए कोर की संख्या को नियंत्रित करने के रूप में '-एनके' के बारे में सोचना बेहतर है। अन्य मामलों में, यदि आप 'फोर्कोस' का उपयोग करते हैं या एफएफआई कॉल करते हैं तो यह महत्वपूर्ण है। –

संबंधित मुद्दे