我正在重叠输入/输出一章的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之前解决。那么这如何异步运行?我本来希望有时会交错(铲前先铲铲)。我的例子太快了吗?如果我再举更多的例子,我会看到这种行为吗?
答案 0 :(得分:2)
无论我做什么,Shovel始终会在Spade之前解决。
好吧,您总是会在铲前通过先调用wait
来要求铲的结果。您总是会在铲子之前开始铲土,因此如果它也几乎总是先解决也就不足为奇了。
一个简单的测试:使用threadDelay 100000 >> getURL "...shovel"
,然后查看网络流量。这将告诉您事情正在同时发生。