2013-06-05 8 views
8

यदि कोई एसटीएम लेनदेन विफल रहता है और फिर से प्रयास करता है, तो writeTChan पर कॉल फिर से निष्पादित हो जाता है ताकि आप दो लिखने के साथ समाप्त हो जाएं, या क्या एसटीएम केवल लेनदेन करता है तो वास्तव में लिखता है? यानी, क्या नींद की बाबर समस्या का यह समाधान वैध है, या यदि ग्राहक को enterShop में लेनदेन पहली बार विफल रहता है तो क्या ग्राहक को दो बाल कटवाने मिल सकते हैं?क्या टीसीएचएन हास्केल एसटीएम में एकीकृत लिखते हैं?

import Control.Monad 
import Control.Concurrent 
import Control.Concurrent.STM 
import System.Random 
import Text.Printf 

runBarber :: TChan Int -> TVar Int -> IO() 
runBarber haircutRequestChan seatsLeftVar = forever $ do 
    customerId <- atomically $ readTChan haircutRequestChan 
    atomically $ do 
    seatsLeft <- readTVar seatsLeftVar 
    writeTVar seatsLeftVar $ seatsLeft + 1 
    putStrLn $ printf "%d started cutting" customerId 
    delay <- randomRIO (1,700) 
    threadDelay delay 
    putStrLn $ printf "%d finished cutting" customerId 

enterShop :: TChan Int -> TVar Int -> Int -> IO() 
enterShop haircutRequestChan seatsLeftVar customerId = do 
    putStrLn $ printf "%d entering shop" customerId 
    hasEmptySeat <- atomically $ do 
    seatsLeft <- readTVar seatsLeftVar 
    let hasEmptySeat = seatsLeft > 0 
    when hasEmptySeat $ do 
     writeTVar seatsLeftVar $ seatsLeft - 1 
     writeTChan haircutRequestChan customerId 
    return hasEmptySeat 
    when (not hasEmptySeat) $ do 
    putStrLn $ printf "%d turned away" customerId  

main = do 
    seatsLeftVar <- newTVarIO 3 
    haircutRequestChan <- newTChanIO 
    forkIO $ runBarber haircutRequestChan seatsLeftVar 

    forM_ [1..20] $ \customerId -> do 
    delay <- randomRIO (1,3) 
    threadDelay delay 
    forkIO $ enterShop haircutRequestChan seatsLeftVar customerId 

अद्यतन मैं तथ्य यह है कि इसके बाद के संस्करण hairRequestChan वैसे भी लेन-देन का हिस्सा बनने की जरूरत नहीं है के बाद जब तक नोटिस नहीं किया था। मैं enterShop में के बादatomically ब्लॉक एक if बयान में एक नियमित Chan का उपयोग करें और writeChan कर सकते हैं। लेकिन यह सुधार करने से सवाल पूछने के पूरे कारण को नष्ट कर दिया गया है, इसलिए मैं इसे यहां छोड़ दूंगा।

उत्तर

11

TChan लेनदेन किए जाने पर संचालन किया जाता है, बस अन्य एसटीएम संचालन की तरह, तो आप हमेशा एक ही लेखन के साथ समाप्त हो जाएंगे, भले ही आपका लेनदेन कितनी बार पुनः प्रयास किया जाए। वे अन्यथा बेकार तरह का होगा।

खुद को समझाने के लिए, इस उदाहरण का प्रयास करें:

import Control.Concurrent 
import Control.Concurrent.STM 
import Control.Concurrent.STM.TChan 

main = do 
    ch <- atomically newTChan 
    forkIO $ reader ch >>= putStrLn 
    writer ch 

reader = atomically . readTChan 
writer ch = atomically $ writeTChan ch "hi!" >> retry 

यह एक अपवाद शिकायत है कि सौदे को अनिश्चित काल के अवरुद्ध है फेंक देते हैं। यदि writeTChan लेनदेन करने से पहले एक लिखित होने का कारण बनता है, तो कार्यक्रम "हाय!" प्रिंट करेगा उस अपवाद को फेंकने से पहले।

+0

महान उदाहरण, धन्यवाद! –

+2

दरअसल, टीचन्स को टीवीर्स ([यहां] (http://hackage.haskell.org/packages/archive/stm/2.1.2.2/doc/html/src/Control-Concurrent-STM-TChan का उपयोग करके शुद्ध हास्केल में कार्यान्वित किया जाता है। एचटीएमएल) टीसीएचएन मॉड्यूल का स्रोत है), इसलिए उन्हें समान मात्रा में अलगाव मिलता है जो टीवीर्स को दिया जाता है। – javawizard

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