问题标签 [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.
concurrency - 原子与参考有何不同?
atom 和 refs 实际有何不同?
我知道原子的声明方式不同,并通过swap!
函数更新,而 refsalter
在dosync
. 然而,内部实现似乎非常相似,这让我想知道为什么我会使用一个而不是另一个。
例如,atoms 的文档页面 ( http://clojure.org/atoms ) 指出:
在内部,交换!读取当前值,将函数应用于它,并尝试比较并设置它。由于另一个线程可能在中间时间更改了该值,它可能必须重试,并在自旋循环中这样做。最终效果是该值将始终是原子地将提供的函数应用于当前值的结果。但是,由于该函数可能会被多次调用,所以它必须没有副作用。
所描述的方法听起来与我用于参考的 STM 非常相似。
clojure - Clojure STM 与原子和代理形式有关系吗?
我正在研究 Clojure 中的并发编程。 http://clojure.org/concurrent_programming
我知道atom,ref和agent形式用于维护程序状态。
只有ref用于协调更新,因此执行更改时使用dosync宏。
所以很明显,这时候就涉及到了STM引擎。
只是想清楚我有以下疑问,
Clojure STM 是否也与原子和代理形式有关系?还是他们只是利用了 java.util.concurrent.atomic 功能?
concurrency - 单个原子与多个参考
使用单个 atom 和 hashmap 与多个 ref 表示状态的权衡是什么?
例如:
对比
非常感谢
multithreading - 停止线程交错输出
下面的程序创建了两个并发运行的线程,每个线程随机休眠一段时间,然后将一行文本打印到标准输出。
输出通常看起来像
您如何确保一次只有一个线程可以写入标准输出?这似乎是 STM 应该擅长的那种事情,但是所有的 STM 事务都必须有STM a
some的类型a
,而打印到屏幕上的动作有 type IO a
,而且似乎没有办法嵌入IO
到STM
中。
haskell - 如何将 F# stm 编写为 >>= 管道
有人可以解释如何将此 FSharpx stm 编写为管道吗?
我正在考虑类似haskell的>>=管道。
谢谢!
更新:为了避免混淆,做一点澄清:
我在想应该能够根据 stm.Bind 和 stm.Return 在 F# 中定义 >>= 运算符。我迷路了,我试图自己做到这一点。
UPDATE2:在Thomas 的回答之后,我发布了我认为看起来还不错的更新版本。如果我理解正确,由于缺少类型类,运算符 >>= 没有与 Haskell 相同的功能。
我同意这对于 F# 来说不是惯用的,但它可能是一个很好的练习。
谢谢!
haskell - 使用 orElse 嵌套的 STM 事务中的验证
这个评论页面描述了 GHC 中的许多细节STM
,但我想澄清几点。
首先,当父级中访问的变量发生变化时,嵌套事务是否失效?
例如我们在线程中有A
:
假设在A
执行嵌套事务takeTMVar b
时,另一个线程B
执行putTMVar a ()
;线程可以A
成功完成其嵌套事务,还是无效(这会让我觉得错了)?
我认为我理解但不介意保证的第二点:在重试上述整个顶级事务A
并最终阻塞的情况下,当任何,或更改A
时将被唤醒是否正确?a
b
c
最后作为奖励,如果我们(或库作者)更改orElse
为,上述事务的语义是否会更改infixr
?
clojure - 事务中的 deref 可能会触发重试 - ref 状态历史的作用是什么?
“Clojure 编程”(Emerick,O'Reilly)指出:
(...) 如果自当前事务开始后由另一个事务提交了新值,则无法提供截至事务开始时的新值。有用的是,STM 注意到了这个问题,并维护了事务中涉及的 refs 状态的有限历史,其中历史的大小随着每次重试而增加。这增加了 - 在某些时候 - 事务不必再重试的机会,因为虽然 ref 被同时更新,但所需的值仍然存在于历史记录中。
接下来,他们给出了一些代码示例来说明问题。
首先,为了说明读取事务只有在所有写入事务完成后才会成功(因此a = 500
):
其次,为了说明该设置:min-history
并:max-history
有助于读取器事务重试(这次a
已成功读取较早 - 值为 33):
我确实理解为什么deref
读取器事务内部会导致它重试(当某些写入器事务正在提交对 ref 的更改时)。我不明白的是这部分:“这增加了 - 在某些时候 - 事务不必再重试的机会,因为虽然 ref 被同时更新,但所需的值仍然存在于历史记录中”。
什么是“期望值”?在上面的示例中,参考历史如何随时间变化?有人可以向我指出一个解释或一些带有时间线的例子,显示参考历史是如何工作的吗?
multithreading - 使用带超时的 Tchan
我有一个 TChan 作为线程的输入,它的行为应该是这样的:
如果 sombody 在特定时间内写入 TChan,则应检索内容。如果在指定时间内没有写入任何内容,则应解除阻塞并继续Nothing
。
我对此的尝试是使用这样的超时功能System.Timeout
:
这似乎有效,但现在我发现,我有时会丢失数据包(它们被写入通道,但在另一侧没有读取。在日志中我得到这个:
其中“Pushing Recorded Packet”是来自一个线程的写入,“Sending Recorded Packet”是从发送者线程中的 TChan 读取。缺少带有 的行Sending Recorded Packet 2 1439
,这表明从 TChan 读取成功。
似乎如果在错误的时间点收到超时,通道就会丢失数据包。我怀疑threadKill
里面使用的功能timeout
和STM一起玩不好。
这个对吗?有人有另一种不会丢失数据包的解决方案吗?