Haskell,频道,STM, - 线程,消息传递



我正在尝试使用channel/stm来实现传递haskell的消息。也许这是一个可怕的想法,并且有一种更好的方法可以在Haskell中实现/使用传递消息。如果是这种情况,请告诉我;但是,我的任务为并发Haskell开了一些基本问题。

我已经听到了有关STM的伟大信息,尤其是在Haskell中实现。由于它支持阅读和写作,并且具有一些安全益处,因此我认为一个人会从那里开始。这提出了我最大的问题:

msg <- atomically $ readTChan chan

Chan是Tchan Int的位置,导致等待通道上有一个值的等待?

考虑以下程序:

p chan = do
    atomically $ writeTChan chan 1
    atomically $ writeTChan chan 2
q chan = do
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan
    -- for testing purposes
    putStrLn $ show msg1 
    putStrLn $ show msg2
main = do
    chan <- atomically $ newTChan
    p chan
    q chan

用ghc -make -threaded编译此程序,然后运行该程序,实际上您获得了1个,然后将2打印到控制台上。现在,假设我们做

main = do 
    chan <- atomically $ newTChan
    forkIO $ p chan 
    forkIO $ q chan

而是。现在,如果我们使用 - 螺纹,它将不打印1个,1或1,然后将2打印到终端;但是,如果您不使用-threaded编译,它总是打印1,然后是2。我想它们并不是真正的同时运行,而它们只是一个接一个地运行。这与下面的内容一致。

现在,在我的思考中,如果我同时运行P和Q;即,我forkio forkio,他们应该能够以相反的顺序运行。假设

main = do
    chan <- atomically newTChan
    forkIO $ q chan
    forkIO $ p chan

现在,如果我在没有图形的情况下对此进行了编译,我再也不会打印到控制台上的任何东西。如果我用 - 线程编译,有时会这样做。虽然,很少有1个,其次是2-通常只有1个或一无所有。我也使用control.concurrent.chan尝试了一下,并获得了一致的结果。

第二个大问题:频道和叉子如何一起播放,上述程序中发生了什么?

无论如何,我似乎不能如此天真地模拟与STM传递的消息。也许Cloud Haskell是解决这些问题的一种选择 - 我真的不知道。有关如何获取消息传递的任何信息,将不序列化~~>写入插座~~>从套接字~~>值得一提的是,将非常感谢。

没有你的想法是正确的 - 这是 TChan s的主意 - 您只是错过了forkIO的一个小点:

问题是您的主线程将不等待用forkIO创建的线程的终止(请参阅此处参考)

因此,如果我使用参考文献中给出的提示

import Control.Concurrent
import Control.Concurrent.STM
p :: Num a => TChan a -> IO ()
p chan = do
    atomically $ writeTChan chan 1
    atomically $ writeTChan chan 2
q chan = do
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan
    -- for testing purposes
    putStrLn $ show msg1 
    putStrLn $ show msg2
main :: IO ()
main = do
    children <- newMVar []
    chan <- atomically $ newTChan
    _ <- forkChild children $ p chan
    _ <- forkChild children $ q chan
    waitForChildren children
    return ()
waitForChildren :: MVar [MVar ()] -> IO ()
waitForChildren children = do
  cs <- takeMVar children
  case cs of
    []   -> return ()
    m:ms -> do
      putMVar children ms
      takeMVar m
      waitForChildren children
forkChild :: MVar [MVar ()] -> IO () -> IO ThreadId
forkChild children io = do
  mvar <- newEmptyMVar
  childs <- takeMVar children
  putMVar children (mvar:childs)
  forkFinally io (_ -> putMVar mvar ())

它可以按预期工作:

d:/Temp $ ghc --make -threaded tchan.hs
[1 of 1] Compiling Main             ( tchan.hs, tchan.o )
Linking tchan.exe ...
d:/Temp $ ./tchan.exe 
1
2
d:/Temp $

,如果您将呼叫切换到pq Too

,当然它将继续工作

相关内容

  • 没有找到相关文章

最新更新