haskell – “forkIO”和“putMVar”:引擎盖下发生了什么?
我希望有人可以帮助我理解为什么以下代码生成下面的输出.代码来自Simon Marlow的书中的Concurrency章节(链接如下).
基于各种函数的描述,我假设第二个putMVar函数应该被阻塞,因为(i)两个putMVar函数都是同一个线程的一部分,并且(ii)已经分配了一个值.显然情况并非如此.很高兴在这里了解“引擎盖下”发生了什么. (注意:本书使用了符号,但我更喜欢>> =符号,因为我认为它更直接 – 因此下面的代码版本.) Link to book import Control.Concurrent main :: IO () main = newEmptyMVar >>= m -> forkIO (putMVar m 'x' >>= _ -> putMVar m 'y') >>= _ -> takeMVar m >>= print >>= _ -> takeMVar m >>= print 输出上面的代码: % ./mvar2 'x' 'y' 解决方法
为了我自己,这是代码中的代码.
main :: IO () main = do m <- newEmptyMVar forkIO $do putMVar m 'x' putMVar m 'y' x <- takeMVar m print x y <- takeMVar m print y 我们拥有的是后台线程和主线程同时在一小块内存上进行通信,MVar称为m. MVar语义是这样的:一个MVar可以是空的或完整的.如果你想读一个MVar并且它是空的那么你必须等到它变满.如果您阅读MV,那么您将尽快解决存储在完整MVar中的值.如果您使用MV,那么您将解析该值,然后在阅读后立即将其清空. 另一方面,当你让MVV将新值放入MVar时,如果MVar为空,你将立即成功.如果已满,则必须等到它变空. 由于在读取和写入方面等待,因此线程在MVar的空虚和丰满度上变得同步. 因此,在这个例子中,我们可以想象许多可能的线性化故事,以了解执行的进展情况.幸运的是,它们的工作方式相同.让我们调用后台线程BG和主线程MN. t = 1 : MN makes a new,empty MVar called 'm' t = 2 : BG puts 'x' in 'm' making it full t = 3 : BG attempts to put 'y' in 'm',but since 'm' is full BG blocks t = 4 : MN attempts to read 'm' and succeeds as it is full t = 5 : BG now places 'y' into the newly empty 'm' t = 6 : BG dies t = 6 : MN prints the value it previously read t = 7 : MN attempts to read 'm' and succeeds as it is full t = 8 : MN prints the value it previously read t = 9 : MN dies 正如我们所看到的,BG被阻止在MV中放入比MN可读取的值更多的值.这会产生您观察到的印刷语义. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |