在 Clojure 中,我们使用 STM 进行并发。
我的问题是 STM 使用数据的时间点值,这不是引入歧义吗?
我们怎么知道访问了什么值?
Clojure 中的 STM 提供(通过ref
s 和dosync
)一个事务上下文,当从外部世界查看时,所有更新都保证“同时”对所有涉及的 refs 进行。
目标是保持系统中值的一致性,典型的例子是两个银行账户之间的资金转移。例如,如果您将 100 美元从账户 A 转移到账户 B,那么您需要同时更改 A 和 B 的金额。
在这个例子中,对于在事务内部处理的金额,读取的值实际上没有歧义,因为在从事务外部读取完成时,只有以下情况是可能的:
在事务内部时,ref
您只读取(并且不修改)的 s可以将它们的值从事务的一个点更改为另一个点,这称为write skew(请参阅Clojure 编程- 第 4 章,Refs,Write Skew)。为了避免这种情况,您可以使用ensure
(而不是deref
),这将导致如果任何这些ref
s 的值发生更改(您仅读取的值),则将重试整个事务。
Clojurians 在这种情况下使用具有非常具体含义的“时间”和“价值”来消除这种歧义。在这种情况下,“时间”是“序列中的时间”或纪元时间,而不是墙上的时间。所以时间描述了这个身份的值序列中的哪个值。
价值是身份在某个时间点不变的内容。该值可以是简单的(原始值或原子值)或复合值,由任意结构的不变值组成。重要的部分是值不会改变,所以如果你想知道使用了哪个值,你可以简单地打印或记录它
我强烈推荐这个关于价值观、状态和身份的视频