Haskell中的并行和并发编程-异步去糖是否可以同步?

时间:2019-02-09 20:21:30

标签: haskell concurrency

我正在重叠输入/输出一章的Haskell中进行并行和并发编程,但我不明白异步实际上是如何异步工作的。

data Async a = Async (MVar a)

async' :: IO a -> IO (Async a)
async' action = do
  var <- newEmptyMVar
  forkIO (do r <- action; putMVar var r)
  return (Async var)

-- if I desugar the do notation for async: 
async'' :: IO a -> IO (Async a)
async'' action = newEmptyMVar >>= \var ->
  (forkIO (action >>= \r -> putMVar var r)) >>
  (return $ Async var)

wait :: Async a -> IO a
wait (Async var) = readMVar var

blah = do
  a1 <- async'' (getURL "http://www.wikipedia.org/wiki/Shovel")
  a2 <- async'' (getURL "http://www.wikipedia.org/wiki/Spade")
  r1 <- wait a1
  r2 <- wait a2
  print (B.length r1, B.length r2)

-- if I desguar the above do block I get this, which looks
-- like a2 won't happen until a1 is finished?
blah' = async''(getURL "http://www.wikipedia.org/wiki/Shovel") >>= \a1 ->
  async''(getURL "http://www.wikipedia.org/wiki/Spade") >>= \a2 ->
  wait a1 >>= \r1 ->
  wait a2 >>= \r2 ->
  (print (B.length r1, B.length r2))

无论我做什么,执行此操作时,Shovel始终在Spade之前解决。那么这如何异步运行?我本来希望有时会交错(铲前先铲铲)。我的例子太快了吗?如果我再举更多的例子,我会看到这种行为吗?

1 个答案:

答案 0 :(得分:2)

  

无论我做什么,Shovel始终会在Spade之前解决。

好吧,您总是会在铲前通过先调用wait来要求铲的结果。您总是会在铲子之前开始铲土,因此如果它也几乎总是先解决也就不足为奇了。

一个简单的测试:使用threadDelay 100000 >> getURL "...shovel",然后查看网络流量。这将告诉您事情正在同时发生。