我正在编写一个离散模拟,其中来自多个线程的请求值累积在一个集中队列中。每 n 毫秒,管理器就会醒来处理请求。当管理器醒来时,它应该在一个单独的步骤中检索中央队列的所有内容。在处理这些时,任何尝试提交到队列的客户端线程都应该阻塞。处理完成后,队列重新打开,管理器返回 sleep 状态。
最好的方法是什么? STM 的重试行为并不是我真正想要的。如果我使用 Chan 或 MVar,则无法阻止客户端在处理过程中将其他请求排队。一种方法是使用 MVar 作为持有队列的 Chan 上的互斥体。还有其他方法可以做到这一点吗?
最佳答案
我必须根据您预期的争用级别进行基准测试才能确切地知道最佳解决方案是什么,但这是我的猜测。
无论您的项目类型是什么,都使用包含[Item]
的MVar
。使用 newMVar []
初始化 MVar
。要将元素添加到中央列表,请使用 modifyMVar_ (return . (item :))
,其中 item
是您要添加到列表中的内容。在处理过程开始时使用 takeMVar
,并在处理过程结束时使用 putMVar []
。
首先,请注意,这在内部不是一个队列。如果您想按照添加顺序处理内容,请在提取列表后反转
列表。
其次,只要这些是您在 MVar
上执行的唯一操作,就不会出现竞争条件。这是因为 MVar
已完全初始化,并且每个操作都是“取出 MVar
的内容,放入其他内容”。在等待后半部分时,操作可能会阻塞,但这不会死锁,并且不会丢失更新。
关于haskell - 通过单个离散步骤删除 Chan 或 MVar 的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4567750/