什么是Clojure volatile?

什么是Clojure volatile?,clojure,Clojure,最近的Clojure 1.7版本中增加了一项功能: volatile已经在许多语言中使用,包括java,但是Clojure中的语义是什么 它有什么作用?什么时候有用?挥发物是一种“更快的原子”,没有原子性保证。它们是因为原子被认为太慢而不能在传感器中保持状态 有一组新的函数(volatile!,vswap!,vreset!,volatile?)用于创建和使用volatile“框”来保存有状态传感器中的状态。挥发物比原子快,但放弃了原子性保证,因此只能与线程隔离一起使用 新的volatile与cl

最近的Clojure 1.7版本中增加了一项功能:

volatile
已经在许多语言中使用,包括java,但是Clojure中的语义是什么

它有什么作用?什么时候有用?

挥发物是一种“更快的原子”,没有原子性保证。它们是因为原子被认为太慢而不能在传感器中保持状态

有一组新的函数(
volatile!
vswap!
vreset!
volatile?
)用于创建和使用volatile“框”来保存有状态传感器中的状态。挥发物比原子快,但放弃了原子性保证,因此只能与线程隔离一起使用


新的volatile与clojure的实际“变量”(与许多其他编程语言一样)非常接近

发件人:

有一组新的函数(
volatile!
vswap!
vreset!
volatile?
)用于创建和使用volatile“框”来保存有状态传感器中的状态。挥发物比原子快,但放弃了原子性保证,因此只能与线程隔离一起使用

例如,您可以像在C中使用变量一样设置/获取和更新它们。 唯一添加的(以及名称)是要添加的
volatile
关键字

这是为了防止JVM进行优化,并确保每次访问时都读取内存位置。 发件人:

Clojure需要更快的Atom变体来管理传感器内部的状态。也就是说,原子完成了这项工作,但它们为传感器提供了太多的能力。具体来说,原子的比较和交换语义增加了太多的开销。因此,确定一个简单的volatile ref类型可以确保将其值基本传播到其他线程,并从任何其他线程读取最新的写操作。虽然更新受竞争条件的限制,但访问由JVM保证控制

解决方案概述:在Java中创建一个具体类型,类似于clojure.lang.Box,但volatile内部支持IDeref,但不支持watches等

这意味着,
volatile仍然可以由多个线程访问(这对于传感器是必需的),但它不允许这些线程同时更改,因为它不提供原子更新

volatile
的语义在以下章节中有很好的解释:

线程安全有两个方面:(1)执行控制,(2)内存可见性。第一个是控制代码何时执行(包括指令的执行顺序)以及它是否可以并发执行,第二个是控制其他线程何时可以看到内存中执行的效果。因为每个CPU与主存之间都有几个级别的缓存,所以在不同CPU或内核上运行的线程在任何给定时刻都可以看到不同的“内存”,因为允许线程获取并处理主存的私有副本

现在让我们看看为什么不使用
var集
瞬态

易失vs-var集 :

如果没有可变的局部变量,人们将被迫使用Recurr函数 循环构造。虽然这一点一开始看起来很奇怪,但实际上也一样 简洁如带突变的循环,由此产生的模式可以 在Clojure的其他地方重复使用,即重现、减少、改变、通勤等 都(逻辑上)非常相似。 [...] 无论如何,Vars 可在适当的时候使用

从而创建带有本地变量的
变量集
等。。 问题是它们是真的,而
var set
的文档字符串告诉您:

变量必须是线程本地绑定的

当然,对于可能在不同线程上执行的core.async,这不是一个选项。他们也慢得多,因为他们做所有的检查

为什么不使用瞬变呢 它们的相似之处在于它们不允许并发访问和优化数据结构。 问题是瞬态只适用于实现
IEditableCollection
的集合。也就是说,它们只是为了避免昂贵的集合数据结构的中间表示。还请记住,瞬变过程并没有被猛击到位,您仍然需要一些内存位置来存储实际的瞬变过程。 挥发物通常仅用于保存标志或最后一个元素的值(例如,请参见
partitionby

总结: Volatile只是java的Volatile的包装器,因此具有完全相同的语义。
永远不要分享它们。只需非常小心地使用它们。

看看它只是一个围绕可变变量的包装器。也许它在事务中使用时会发出警告,类似于
io读取:
易失性
不是线程安全的,所以它应该只在一个线程中使用,就像在单线程转换器的情况下一样。@claj这不太正确,您可以在不同的线程中使用volatile。
atom
s或
transients
可以实现的原子更新刚刚消失。@Andre,你说得对。java中的易失性指针写入是原子的(幸运的是:),并且访问顺序是有保证的。谢谢你纠正我!出色的回答,通过简洁但技术上正确的回答,预期后续问题。