问题标签 [ioref]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - 共享 IORef 时,只要我使用 atomicModifyIORef 编写,使用 readIORef 读取是否安全?
IORef
如果我在多个线程之间共享一个,并使用atomicModifyIORef
它来写入:
用普通的 old 读取值是否安全readIORef
?或者修改后是否有机会readIORef
在另一个线程中返回旧值atomicModifyIORef
?
我认为这就是文档所暗示的:
atomicModifyIORef 充当重新排序的障碍。多个 atomicModifyIORef 操作以严格的程序顺序发生。永远不会观察到 atomicModifyIORef 发生在任何更早(按程序顺序)的 IORef 操作之前,或在任何以后的 IORef 操作之后。
我只是想确定一下。
haskell - 共享可变状态:何时使用 IORefs
我有一个写入 Map 和 PSQ 的主线程。在 Map 和 PSQ 中,我使用相同的键,因此通过查看 PSQ,可以找到具有最小优先级的条目,复杂度为 O(1),并映射到 Map 中的值。
现在,虽然我的主线程在需要时添加/修改了 Map 和 PSQ,但我有第二个线程不断(forever $ do
)查看 PSQ 以确定最旧的密钥何时是 N 毫秒前,然后应该刷新它。
为此,两个线程都需要查看相同的可变数据。这里保持状态的最佳方法是什么?这会是 IOREfs 的情况吗?还有什么可能的方法来解决这个问题?
“一些”预阿尔法代码在这里:
haskell - Haskell并发使用简单的IORef?
我一直在问一些关于 Haskell 并发的问题,特别TVar
是TVar
.
相反,我提出了这个解决方案。
(1) 将程序中的所有共享数据包装在一个数据结构中,并将其包装在一个IORef
. (2) 只需使用atomicModifyIORef
.
我相信这可以防止死锁和活锁(而 TVar 只能防止前者)。此外,因为atomicModifyIORef
只是将另一个 thunk 链接到一个链中(这是几个指针操作),所以这不是瓶颈。对数据的所有实际操作都可以并行完成,只要它们不相互依赖即可。Haskell 运行时系统会解决这个问题。
然而我觉得这太简单了。有没有我错过的“陷阱”?
haskell - Haskell:尝试并行`atomicModifyIORef`实现
据我了解,对IORef
s 的修改非常快,它们所涉及的只是更新一个 thunk 指针。当然,读者(即想要在他们的网页上看到价值的人)将需要花时间来评估这些 thunk(如果作者没有回读结果,这可能会增加)。
我认为最好开始IORef
并行地实际评估修改 thunk,因为在许多情况下,它们可能无论如何都必须在某个时候进行评估(显然,这将破坏无限的数据结构)。
因此,我编写了以下函数,其签名类似于atomicModifyIORef
:
这似乎有效(测试代码here)。我在这里做错了什么吗?还是有更好的方法来做到这一点?
编辑:第二次尝试
受以下卡尔回答的启发。我们实际上存储force newdata
到IORef
. 这和反正是一样newdata
的,但是显示了我们想要force newdata
稍后保留的运行时,所以它不会垃圾收集火花。
performance - Haskell:并发数据结构指南
我一直在尝试理解并发,并且一直在尝试找出更好的方法,一个大IORef
锁或多个TVar
s。我已经得出以下指导方针,我们将不胜感激,关于这些是否大致正确或我是否错过了重点。
让我们假设我们的并发数据结构是一个映射m
,像 一样访问m[i]
。还可以说我们有两个函数,f_easy
并且f_hard
. f_easy
速度很快,需要f_hard
很长时间。我们将假设 的参数f_easy/f_hard
是 的元素m
。
(1) 如果您的交易大致如下所示m[f_easy(...)] = f_hard(...)
,请使用IORef
with atomicModifyIORef
。懒惰将确保m
它只被锁定很短的时间,因为它是用一个 thunk 更新的。计算索引有效地锁定了结构(因为有些东西会被更新,但我们还不知道是什么),但是一旦知道那个元素是什么,整个结构上的 thunk 就会移动到仅在那个特定元素上的 thunk ,然后只有那个特定的元素被“锁定”。
(2) 如果你的交易看起来大致是这样m[f_hard(...)] = f_easy(...)
的,并且不要冲突太多,使用很多TVar
s。在这种情况下使用 anIORef
将有效地使应用程序成为单线程,因为您不能同时计算两个索引(因为整个结构上会有一个未解决的 thunk)。TVar
s 让你同时计算出两个索引,但是,不利的是,如果两个并发事务都访问同一个元素,并且其中一个是写入,则必须废弃一个事务,这会浪费时间(本来可以在别处使用)。如果这种情况经常发生,你可能会更好地使用来自 (通过黑洞)的锁IORef
,但如果它不经常发生,你将获得更好的TVar
s 并行性。
基本上在情况(2)中,IORef
您可能会获得 100% 的效率(没有浪费的工作)但只使用 1.1 个线程,但TVar
如果您的冲突数量较少,您可能会获得 80% 的效率但使用 10 个线程,所以您仍然结束即使浪费了工作,速度也提高了 7 倍。
haskell - 在纯代码中避免 IORef
我注意到Data.UnionFind使用 IO monad 通过 IORefs 提供指针。我想每个人在以纯代码在本地使用它时都会愉快地调用unsafePerformIO
它,因为数据结构很好理解,但是..
这种数据结构是否有规范的清洁方法?也许是 IO 的包装器,它通过禁止大多数 IO 操作使不可避免unsafePerformIO
的不安全“看起来”变得不那么安全?
haskell - 什么haskell数据结构来存储可变树
我正在考虑用haskell编写一个浏览器。中央数据结构将是表示文档的可变树。除了使用完全由 iorefs 组成的树之外,还有更好的解决方案吗?
我希望避免这样的事情:(data DomNode = DomNode TagName NodeProperties (IORef DomNode) [IORef DomNode]
标签,属性,父母,孩子)
问题是 javascript 可以保留树中节点的引用,它可以改变(添加子节点、修改属性)它引用的任何节点,以及遍历它的父节点。
编辑:
我意识到您需要以某种方式使用可变状态 - 因为您可以保留对从树中删除或在树中移动的节点的引用。如果你通过基于树结构的东西引用了元素,那么这个引用将是无效的。
haskell - StateT 与 ReaderT IORef 的异常处理
通过坚持 an 来通过异常维护状态似乎IORef
比尝试使用 State Monad 容易得多。下面我们有 2 个替代的状态单子。一种用途StateT
,另一种ReaderT IORef
。可以轻松地在ReaderT IORef
最后一个已知状态上运行最终处理程序。
那么在 main 函数结束时,即使抛出异常,我如何运行一个最终处理程序,它可以访问 State Monad 的最后一个现有状态?或者是ReaderT IORef
最佳选择还是有更好的选择?
haskell - 为什么我不能将值写入 IORef 但可以读取它
在 haskell 中,我需要一个全局变量,所以我选择使用 IORef 插槽,这是我的计划:
我的计划是当执行器评估“调用”节点时,它将参数保存到插槽中。然后,当评估“ARGs”节点时,将读取该备忘录槽。
但无论我做什么,我只能读取 9999 但不能将新值写入该插槽。
即使我尝试过:
它仍然会导致备忘录 = 9999。为什么?
haskell - 何时使用 STRef 或 IORef?
STRef 和 IORef 之间到底有什么区别,我什么时候使用它们?据我所知,它们都是可变状态,那么它们存在的意义何在?