Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 使用TChan的管道式操作_Multithreading_Haskell_Stm - Fatal编程技术网

Multithreading 使用TChan的管道式操作

Multithreading 使用TChan的管道式操作,multithreading,haskell,stm,Multithreading,Haskell,Stm,我想在两个线程之间实现一个管道。我有一个线程A,它接收数据,处理数据,并将其发送给线程B。我有一个MVar,它检查数据是否被完全处理 但是,我遇到了一个异常***异常:STM事务中的线程被无限期阻塞 为什么我的线程被阻塞?我认为当第一个线程在通道上写入数据时,第二个线程可以读取数据 fstPipe :: (a -> b) -> TChan b -> MVar () -> [a] -> IO () fstPipe f chIn m xs = do ( mapM

我想在两个线程之间实现一个管道。我有一个线程A,它接收数据,处理数据,并将其发送给线程B。我有一个MVar,它检查数据是否被完全处理

但是,我遇到了一个异常
***异常:STM事务中的线程被无限期阻塞

为什么我的线程被阻塞?我认为当第一个线程在通道上写入数据时,第二个线程可以读取数据

fstPipe :: (a -> b) -> TChan b -> MVar () -> [a] -> IO ()
fstPipe f chIn m xs = do
    ( mapM_(\x-> atomically $ writeTChan chIn $ f x) xs) >> putMVar m ()

pipelineDone channel mIn = do
    isDone <- fmap isJust $ tryTakeMVar mIn
    isEmpty <- atomically $ isEmptyTChan channel
    return $ isDone && isEmpty

lastPipe f chIn mIn = iter 
    where iter = do
        atomically $ fmap f $ readTChan chIn
        isDone <- pipelineDone chIn mIn
        unless isDone $ iter

pipeline = do
    chIn <- atomically newTChan
    m <- newEmptyMVar
    first <- async $ fstPipe reverse chIn m $ replicate 10 [1..500]
    last <- async $ lastPipe print chIn m
    wait first
    wait last
fstPipe::(a->b)->TChan b->MVar()->[a]->IO()
fstPipe f chIn m xs=do
(mapM(\x->atomically$writeTChan-chIn$fx)xs)>>putMVar m()
pipelineDone通道最小值=do

isDone我认为这是一种竞赛条件:

  • putMVar
  • 前进
    lastPipe
    阅读所有内容,然后调用
    pipelineDone
  • pipelineDone
    返回
    False
    ,因为
    putMVar
    尚未完成
  • lastPipe
    将尝试从频道读取
  • putMVar
    执行,但为时已晚

现在,
lastPipe
卡在一个空通道上读取。

在同一代码块中使用STM和信号量对我来说似乎很奇怪。。。为什么不在STM中完成整个过程

特别是,为什么不使用一个
TChan(可能是x)
,而
Nothing
表示序列的结束


另外,请注意,您的
fstPipe
可能只是生成了一堆未经计算的thunk,并立即将它们放入
TChan
,而没有实际计算任何内容。您可能需要一个
seq
或类似的命令来强制在该线程上执行一些实际工作。

您的问题在于
管道完成的逻辑。目前,您有:

pipelineDone channel mIn = do
  isDone <- fmap isJust $ tryTakeMVar mIn
  isEmpty <- atomically $ isEmptyTChan channel
  return $ isDone && isEmpty

这将只是轮询MVar,而不是实际清空它。

谢谢!因此,如果我理解得很好,如果我写“writechan chin$seq$fx”,它将计算fx,然后将其添加到频道?如果你写
writechan ch$!fx
(注意
$!
而不是
$
),这将强制
f
的结果为弱头范式。如果你想进一步评估。。。这是另一个问题。搜索以前的答案。;-)
pipelineDone channel mIn = do
  stillRunning <- isEmptyMVar mIn
  isEmpty <- atomically $ isEmptyTChan channel
  return $ (not stillRunning) && isEmpty