帮助理解Haskell中的MVar示例
我正在试图理解中的MVar示例-帮助理解Haskell中的MVar示例,haskell,concurrency,Haskell,Concurrency,我正在试图理解中的MVar示例- data SkipChan a=SkipChan(MVar(a,[MVar()]))(MVar()) newSkipChan::IO(SkipChan a) newSkipChan=do sem IO() putSkipChan(SkipChan干管)v=do (u,sems)putMVar sem())sems getSkipChan::SkipChan a->IO a getSkipChan(SkipChan主扫描电镜)=do takeMVar扫描电镜 (五
data SkipChan a=SkipChan(MVar(a,[MVar()]))(MVar())
newSkipChan::IO(SkipChan a)
newSkipChan=do
sem IO()
putSkipChan(SkipChan干管)v=do
(u,sems)putMVar sem())sems
getSkipChan::SkipChan a->IO a
getSkipChan(SkipChan主扫描电镜)=do
takeMVar扫描电镜
(五、中小型企业)IO(SkipChan a)
dupSkipChan(SkipChan main)=do
扫描电镜
您是正确的,另一个线程可能会调用putMVar main
并将putSkipChan
搞砸。但是创建上述代码的模块不会导出SkipChan
构造函数,因此这样的恶意操作是不可能的
dupSkipChan
创建一个名为sem
的新emptyMVar
,并将其添加到main中的列表中。它不会添加在newSkipChan
中创建的现有文件。因此,没有障碍
向其他读者进一步解释这个问题和评论:这个想法是可能有多个读者线程。最初,SkipChan main sem1是唯一一个这样的读卡器dupSkipChan
生成一个SkipChan主sem2
。如果有数千个读卡器,那么您不希望在putSkipChan
中通知所有读卡器的新值,因此设计是getSkipChan
将其sem放入main中的列表中。在newSkipChan
和dupSkipChan
中初始化SkipChan
还包括将新的空sem
放入main中的列表
上述初始化和设计意味着第一个getSkipChan
获取最近写入的过去值(或第一个值到达的块)。该SkipChan
上的未来getSkipChan
将始终获得比以前获得的任何值都新的值,并且如果该值已经可用,这些值将不会被阻止
data SkipChan a = SkipChan (MVar (a, [MVar ()])) (MVar ())
newSkipChan :: IO (SkipChan a)
newSkipChan = do
sem <- newEmptyMVar
main <- newMVar (undefined, [sem])
return (SkipChan main sem)
putSkipChan :: SkipChan a -> a -> IO ()
putSkipChan (SkipChan main _) v = do
(_, sems) <- takeMVar main
putMVar main (v, [])
mapM_ (sem -> putMVar sem ()) sems
getSkipChan :: SkipChan a -> IO a
getSkipChan (SkipChan main sem) = do
takeMVar sem
(v, sems) <- takeMVar main
putMVar main (v, sem:sems)
return v
dupSkipChan :: SkipChan a -> IO (SkipChan a)
dupSkipChan (SkipChan main _) = do
sem <- newEmptyMVar
(v, sems) <- takeMVar main
putMVar main (v, sem:sems)
return (SkipChan main sem)