- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现一个用于并发应用程序的堆栈。我想要以下语义: push
永远不应该阻塞,而 pop
应该阻塞空堆栈上的调用线程,但仍然允许 push
es 。我按如下方式实现(底部不相关的位):
data Stream a = Stream a (MVar (Stream a))
data Stack a = Stack (MVar (Int, MVar (Stream a)))
popStack :: Stack a -> IO a
popStack (Stack stack) = do
(sz, mvar) <- takeMVar stack
mbStream <- tryTakeMVar mvar
case mbStream of
Nothing -> putMVar stack (sz, mvar) >> popStack (Stack stack)
Just (Stream x xs) -> putMVar stack (sz-1, xs) >> return x
如果流MVar
为空,我必须释放堆栈上的锁并重试。然而,这看起来像是一个拼凑:如果一个线程在一个空堆栈上调用 pop
,它可能会在挂起之前循环几次,即使 MVar
不会变满,而该线程正在执行。有没有更好的方法利用 MVar 来编写具有所需语义的 pop ?
import Control.Concurrent.MVar
import Control.Monad
import Control.Concurrent
import Text.Printf
newStack :: IO (Stack a)
newStack = do
stream <- newEmptyMVar
Stack <$> newMVar (0, stream)
pushStack :: Stack a -> a -> IO ()
pushStack (Stack stack) val = do
(sz, stream) <- takeMVar stack
stream' <- newMVar (Stream val stream)
putMVar stack (sz+1, stream')
test = do
s <- newStack
_ <- forkIO $ mapM_ (\a -> printf "pushing %c... " a >> pushStack s a >> threadDelay 100000) ['a' .. 'z']
_ <- forkIO $ do
replicateM 13 (popStack s) >>= printf "\npopped 13 elems: %s\n"
replicateM 13 (popStack s) >>= printf "\npopped 13 elems: %s\n"
threadDelay (5*10^6)
putStrLn "Done"
最佳答案
这不是很令人兴奋,但最简单的解决方案是使用 STM
(如果您使用 cabal,您的依赖项列表中将需要 stm
包)。
import Control.Concurrent.STM
newtype Stack a = Stack (TVar [a])
new :: STM (Stack a)
new = fmap Stack $ newTVar []
put :: a -> Stack a -> STM ()
put a (Stack v) = modifyTVar' v (a:)
get :: Stack a -> STM a
get (Stack v) = do
stack <- readTVar v
case stack of
[] -> retry
(a:as) -> do writeTVar v as
return a
您可以使用 retry
获得所需的阻止行为,其实现方式是线程不会被唤醒,直到 TVar
更改为 []
以外的内容。这也很好,因为您现在可以在更大的组合原子事务中使用堆栈,并且不必担心确保异常不会破坏您的结构。
如果您尝试通过大量线程竞争读取和/或写入来实现高性能并发,您可能会发现这不够聪明。在这种情况下,您可能会喜欢围绕 fetch-and-add
设计一个结构。基于计数器 atomic-primops ,或者看看 hackage 上还有什么可用的。
关于haskell - 使用 MVar 实现并发堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23471594/
我看到混合使用 MVar 和 Weak 时出现问题:即使 MVar 仍然可以从函数的范围访问(并且主线程正在阻塞它),Weak 认为它应该被最终确定。这种行为似乎只有在启用优化的情况下编译时才会发生。
对于通过 self 访问实例变量或仅通过名称访问实例变量(在类内部工作时)之间的区别,我有些困惑。 例如,上这门课: //In .h file: @interface Register : NSObj
我正在使用 MVar 构建线程安全的共享状态并且由于要求,我需要一些公平保证(如果两个线程一个接一个地询问 MVar 下的状态,那么一旦状态可用,线程就会按照他们要求的顺序接受它)。 我在 MVar
我正在尝试制作一个在用户按下回车之前打印箭头的程序(参见下面的代码)。 问题是当我按下回车时,我在控制台中看到了“stop”字符串,但它并没有改变 outputArrows 函数中 m 的值。 如何共
给定以下“TinyUrl”网络应用程序: import Prelude () import Prelude.Compat import Data.Aeson.Types import GHC.Gene
我有一个看起来像这样的数据类型: data PageLogCommand = LogPage Page | Stop (MVar ()) 我想创建一个 Gen
我正在尝试使用 Haskell 创建一个简单的服务器。当客户端连接到服务器时,服务器记录他们的地址。服务器每 n 微秒发送一次广播。 这是服务器 data Server = Server { sS
documentation for Control.Exception 描述哪些操作可以抛出异步异常,即使在 mask 内ed block,说:“以下操作保证不可中断” takeMVar if the
我想对 MVar 中的值进行有效计算或 Ref和 原子 更新它以防计算成功或放回初始值(在 MVar 的情况下)/在操作失败的情况下什么也不做(在 Ref 的情况下)。 一、引用案例 val ref
我有一个工作线程,它从 MVar 重复读取数据并对其执行一些有用的工作。一段时间后,程序的其余部分会忘记该工作线程,这意味着它将等待空的 MVar 并变得非常孤独。我的问题是: Will the MV
我制作了以下特定于 IO monad 的函数: memoIO :: MonadIO m => m a -> IO (m a) memoIO action = do ref MRef r m a
我一直在尝试调试使用多个 MVar 时的问题,但没有成功。 我的代码使用两个 MVar:一个用于存储服务器当前状态,另一个用于在客户端线程之间传递网络事件。然而,在多次连接和断开连接之后,服务器在新客
我正在尝试实现一个用于并发应用程序的堆栈。我想要以下语义: push 永远不应该阻塞,而 pop 应该阻塞空堆栈上的调用线程,但仍然允许 pushes 。我按如下方式实现(底部不相关的位): data
假设我有多个线程正在从文件中读取,并且我想确保在任何时间点只有一个线程正在从文件中读取。 实现这一点的一种方法是使用 mvar :: MVar ()并确保如下互斥: thread = do ..
我想要一个功能 takeAnyMVar :: NonEmpty (MVar a) -> IO (MVar a, a) 等待多个 MVar s 同时返回第一个 MVar (及其值(value))变得可用
如何对 [MVar a] 列表进行排序?使用 a 作为要在排序中进行比较的元素。例如: sortList :: [MVar Int] -> [MVar Int] 我想不出不破坏其他线程的方法。 更新:
我很难理解 Haskell 中 IORef 类型和 MVar 类型之间的基本区别。有人可以帮我解决这个问题吗?他们似乎解决了同样的问题。 MVar 似乎是针对多线程的,但是 IORef 有 atomi
我想要一个小操作,其中一个线程向共享状态添加一些值,而另一个线程取出该值并打印它。这是分别使用 TMVar 和 MVar 的两个版本。 TMVar 版本无法正常工作,它不断打印出第一个值。 STM第一
只是好奇。如果我使用 forkIO 生成 2 个线程,则可以使用 MVar 完成它们之间的通信。我想知道当使用使用 par 创建的并行 Haskell Spark 时是否同样适用。我知道 par 不会
在 Control.Proxy pipes-3.1.0的教程包中,作者提供了这个功能: cache :: (Proxy p, Ord key) => key -> p key val key val
我是一名优秀的程序员,十分优秀!