TChan写入是否集成到Haskell STM中?
如果STM事务失败并重试,对TChan写入是否集成到Haskell STM中?,haskell,stm,Haskell,Stm,如果STM事务失败并重试,对writechan的调用是否会重新执行,从而导致两次写入,或者STM是否仅在事务提交时才实际执行写入?i、 例如,这种解决睡眠理发师问题的方法有效吗?或者,如果enterShop中的交易第一次失败,客户可能会理发两次 import Control.Monad import Control.Concurrent import Control.Concurrent.STM import System.Random import Text.Printf runBarber
writechan
的调用是否会重新执行,从而导致两次写入,或者STM是否仅在事务提交时才实际执行写入?i、 例如,这种解决睡眠理发师问题的方法有效吗?或者,如果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
import-Control.Monad
导入控制。并发
导入控制.Concurrent.STM
导入系统。随机
导入文本.Printf
runBarber::TChan Int->TVar Int->IO()
runBarber HairutRequestChan seatsLeftVar=永远$do
customerId IO()
enterShop hairutrequestchan seatslefvar customerId=do
putStrLn$printf“%d进入店铺”客户ID
hasEmptySeatTChan
操作是在提交事务时执行的,就像其他STM操作一样,因此无论事务重试多少次,您都将以一次写入结束。否则它们就没用了
要说服自己,请尝试以下示例:
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
导入控制。并发
导入控制.Concurrent.STM
导入控制.Concurrent.STM.TChan
main=do
ch>=putStrLn
作家
读卡器=原子。雷德尚
writer ch=atomically$writeTChan ch“嗨!”>>重试
这将引发一个异常,抱怨事务被无限期阻止。如果writechan
在提交事务之前导致写入,程序将在抛出该异常之前打印“hi!”。事实上,TChan是使用TVars(TChan模块的源代码)在纯Haskell中实现的,因此它们收到的隔离程度与TVars相同。