问题标签 [stm]
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 - STM 是否为现有数据结构提供细粒度锁定?
阅读 Bartosz Milewski 在 STM 上的精彩博客文章,我很高兴阅读以下内容:
但是要考虑一个重要的事实:STM 是非常细粒度的。例如,当您将项目插入树中时,STM 事务只会锁定您实际修改的节点。STM 将轻松击败每棵树使用一个全局锁的解决方案。
但是,据我了解,这种行为不是自动的,是吗?如果我使用 a TVar (Map k a)
,它不会充当整个地图上的单个全局锁吗?为了获得这种细粒度行为的好处,我(或某人)必须实现一个内部TMap
包含的地图替换(例如),对TVars
吗?
这似乎是一个显而易见的问题,但在阅读 STM 实现时,我对TVar
s 的读取和内存位置的读取感到困惑。我只是想确保我做对了!
Bartosz 进一步说:
由于存在死锁的风险,每个节点的手动锁定很难正确实施。
据我了解,与 STM 的区别在于,虽然 STM 实现实际上使用了手动锁定解决方案可能使用的锁,但锁的实际获取和释放是由运行时处理的,而不是程序员 - 对吗?
haskell - Haskell 一种方式`dupTChan`
有没有这样的功能。除了当你这样做:
写入的任何内容都会写入oldChan
,newChan
但不是相反?
java - 使用 Deuce STM 排队
我是 Deuce STM 的新手,想知道如何使用 Deuce STM 实现队列。这是我目前的工作实施 -
Node 类包含两个字段 - 值和指向下一个字段的指针。
这是实现它的正确方法吗?我们是否必须手动抛出事务异常?如果这是正确的,那么我们如何衡量被中止或重试的事务数?
haskell - 如何在 Haskell 中产生并发计算?
如果我有一个函数进行四次非常长的计算并返回一个包含四次计算结果的列表,但是每个计算不依赖于另一个,你如何在 Haskell 中“并行化”它?
为了更好地解释我的问题,这是我想到的 Clojure 示例:
您可以生成三个额外的线程,例如:
类似于 Haskell 中的内容是否是等价的?
我需要 rpar/rseq c4 吗?
rpar/rseq 是进行这种并发计算的方式吗?
如果我不 rseq,稍后当我尝试访问返回的列表中的返回值时,程序会等待吗?
这是透明的,还是您需要在使用“@”时执行 Clojure 中发生的“deref”之类的操作?
f# - FSharpx.Stm 如何处理冲突?
假设我们有以下代码:
...并且两个线程正在执行事务,并且读/写按以下顺序发生:
- 线程A readTVar1
- 线程A读取TVar2
线程A writeTVar1
线程B读取TVar1
- 线程B读取TVar2
线程B writeTVar1
线程A writeTVar2
- threadB writeTVar2 --> 冲突!!!
考虑到第 8 步的冲突,我看到解决问题的两种可能性?
可能性1:重试整个事务,即threadB再次执行readTVar1、readTVar2、writeTVar1、writeTVar2
可能性 2:线程 B 回到 readTVar2 并仅重试readTVar2 和 writeTVar2
那么事务重试是如何发生的呢?
谢谢!
scala - STM 与 AKKA 的并发性
我有需要以并发方式更新的数据。此数据作为单例对象存在于 PlayFramework 中。在这种情况下会使用 AKKA 更好地更新这些数据,还是应该使用 STM?他们似乎都在做同样的事情,所以我想知道哪个更好。
这两种解决方案在共享状态并发方面有什么区别。
谢谢
haskell - 我可以使用模板 haskell 来定义缺少的功能吗?
我有一种情况,我需要在不同的机器上编译一些 Haskell 代码。这些机器中至少有一台具有相当旧的Control.Concurrent.STM版本,它不知道modifyTVar
。我目前的解决方法是从更新版本的包中复制 modifyTVar 的代码。这让我想知道,是否可以使用模板 Haskell 来检查一个函数是否已经定义并且只定义它,如果它丢失了。我知道正确的解决方案可能是获取更新的软件包,但这种情况让我很好奇。
haskell - 如何为 Haskell STM 通道实现相当于 Go 的 select 语句?
Go 语言有一个select
语句,可用于轮询多个通道并根据哪个通道首先非空来执行特定操作。
例如
这将等到或非空,然后如果例如chanA
非空,它将读取并将结果存储在 中,然后调用。也可以添加一个子句,这意味着该语句不会在通道上等待,而是在所有通道为空时执行该子句的任何内容。chanB
chanC
chanB
chanB
b
baz(b)
default:
select
default
TChan
在 Haskell 中为 STM 实现这样的最佳方法是什么?它可以通过 if-else 链天真地完成:检查每个 chanisEmptyChan
是否为空,如果它不为空,则从中读取并调用适当的函数,或者retry
如果所有通道都为空则调用。我想知道是否会有更优雅/惯用的方式来做到这一点?
请注意,Go 的select
语句也可以在其 case 中包含 send 语句,并且只有在其通道为空时才会完成一个 send 语句。如果该功能也可以复制,那就太好了,尽管我不确定是否会有一种优雅的方式来做到这一点。
只是稍微相关,但我刚刚注意到,我不确定在哪里发布:在Control.Monad.STM页面的描述中有一个错字retry
:
“实现可能会阻塞线程,直到它读取的 TVar 之一被更新。”
clojure - 如何让长时间运行的事务在 clojure 中快速失败
假设以下代码中的 ref 在其他事务以及下面的事务中被修改,我担心这个事务将一直运行到提交时,提交失败,然后重新运行事务。
这是我的全部恐惧:
- 调用 modify-ref,启动事务(称为 A),并开始长时间运行计算
- 另一个事务(称为 B)启动,修改 my-ref,并返回(成功提交)
- 长时间运行的计算一直持续到完成
- 事务 A 尝试提交但失败,因为 my-ref 已被修改
- 使用 my-ref 的新值重新启动事务(称为 A')并退出,因为 some-prop 不正确
这就是我想要发生的事情,也许这就是发生的事情(我只是不知道,所以我在问这个问题:-)
当事务 B 提交 my-ref 时,我希望事务 A 立即停止(因为 my-ref 的值已更改)并使用新值重新启动。是这样吗?
我想要这种行为的原因是长时间运行计算不会将所有 CPU 时间浪费在现在已经过时的计算上。
我考虑过使用ensure
,但我不确定如何在这种情况下使用它或者是否有必要。
haskell - Haskell STM 总是成功的
haskell 的 stm 库中有一个函数,其类型签名如下:
根据我对 Haskell 中 STM 的了解,在执行 STM 计算时,有三种方式可能会“出错”(松散地使用该术语):
- 已读取的 TVar 的值被另一个线程更改。
- 违反了用户指定的不变量。这似乎通常是通过调用
retry
使其重新开始来触发的。这有效地使线程阻塞,然后在读取集中的 TVar 更改后重试。 - 抛出异常。调用
throwSTM
会导致这种情况。这与前两个不同,因为事务不会重新启动。相反,错误被传播,或者使程序崩溃,或者被 IO monad 捕获。
如果这些是准确的(如果不是,请告诉我),我无法理解alwaysSucceeds
可能会做什么。该always
函数似乎是建立在它之上的,它似乎可以不写alwaysSucceeds
为:
的文档alwaysSucceeds
说:
alwaysSucceeds 添加了一个新的不变量,当传递给 alwaysSucceeds、当前事务结束时以及每个后续事务结束时,该不变量必须为真。如果它在任何这些点失败,那么违反它的事务将被中止,并且由不变量引发的异常被传播。
但是由于参数是类型STM a
(多态 in a
),它不能使用事务返回的值用于决策的任何部分。因此,它似乎会寻找我之前列出的不同类型的故障。但那有什么意义呢?STM monad 已经处理了失败。将它包装在这个函数中会如何影响它?为什么类型的变量a
会被删除,导致STM ()
?