哈斯克尔:TVar:预防饥饿

Cli*_*ton 7 concurrency haskell ghc stm tvar

我正在考虑使用TVar在Web应用程序中存储某些状态(可以在重新启动时重新创建).然而,TVar的争论方面关注我.似乎频繁的短期交易可以通过不断地中断它们来匮乏更长的交易.此外,随着更长时间运行的事务不断重启,这会增加CPU的负载,趋向于进一步增加这些事务的长度.最终我觉得这可能导致服务器完全没有响应.

考虑到这一点,我有以下问题:

(1)TVar(或其他数据类型)可以使用锁,而不是同时尝试/重试.

(2)可以的TVar(或其它数据类型)有一些不同的竞争机制,即"让交易运行另一个事务前一秒钟跑",或至少一些保证交易将最终完成(即竞争算法,以防止饥饿的更长时间的交易).

Pet*_*ter 5

除非你改变STM系统本身的运行时代码,否则我认为没有办法保证饥饿自由.在我看来,引入锁以避免争用,TVars首先是STM的目的,因为使用STM的全部目的是摆脱经典的易出错的基于锁的并发编程方法.

当然,饥饿可能会导致重大的性能损失,但这只是假设这种大型交易实际上是必要的.我试图记住的一个设计原则是TVars在较低的粒度级别使用.例如,您可以使用更符合STM的数据结构(如跳过列表[1]),而不是将整个Data.Map放入a中TVar,这可能会在每次更新条目时引起争用.

[1] http://hackage.haskell.org/package/tskiplist


scl*_*clv 3

仅当您有许多便宜的更新数据的事务和一些昂贵的读取数据的事务时,这才是一个问题。也许是对实时更新的数据集的分析。

如果您确实担心这一点,请考虑使用标志 TVar。将其设置为 false 并在每次廉价交易开始时检查它是否为 false,retry否则调用。然后只需在进入长时间运行的事务之前将其设置为 true,并在退出时将其设置为 false。或者,您可以简单地在TMVar. 您的长时间运行计算以原子方式获取 tmvar,执行其感觉,然后返回它。其他事务完全在单个实际 STM 事务中进行。

还要记住,长时间运行的 STM 交易有点棘手。由于懒惰,您可以便宜地将昂贵的值放入 var 中。您还可以非常快速地从一大堆变量中读取数据的“快照”。要拥有真正长时间运行的事务,您需要从一大堆变量中读取数据,然后根据您所读取的内容,计算要向哪些变量写入新值(或从中读取值),以及该计算本身一定很贵。很可能您一开始就没有处于这种情况!