Se una transazione STM fallisce e riprova, la chiamata a writeTChan
viene rieseguita in modo da terminare con due scritture oppure STM esegue effettivamente la scrittura solo se la transazione viene eseguita? vale a dire, questa soluzione al problema del barbiere addormentato è valida oppure potrebbe un cliente ottenere due scarti se la transazione in enterShop
non riesce la prima volta?Le scritture TChan sono integrate in Haskell STM?
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
UPDATE non ho notato fino a dopo il fatto che quanto sopra hairRequestChan
non deve essere parte della transazione in ogni caso. Posso usare un normale Chan
e fare il writeChan
in una dichiarazione if
dopo il il blocco atomically
in enterShop
. Ma fare in modo che questo miglioramento distrugga l'intera ragione per fare la domanda, quindi lo lascerò così com'è.
Grande esempio, grazie! –
Infatti, i TChan sono implementati in puro Haskell usando TVars ([qui] (http://hackage.haskell.org/packages/archive/stm/2.1.2.2/doc/html/src/Control-Concurrent-STM-TChan. html) è la fonte del modulo TChan), quindi ricevono la stessa quantità di isolamento rispetto a TVars. – javawizard