gpt4 book ai didi

clojure - Clojure volatile 是什么?

转载 作者:行者123 更新时间:2023-12-03 07:08:54 24 4
gpt4 key购买 nike

最近的 Clojure 1.7 版本中增加了一个内容:volatile!

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

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

最佳答案

新的 volatile 与 clojure 中的真实“变量”(就像它来自许多其他编程语言一样)一样接近。

来自the announcement :

there are a new set of functions (volatile!, vswap!, vreset!, volatile?) to create and use volatile "boxes" to hold state in stateful transducers. Volatiles are faster than atoms but give up atomicity guarantees so should only be used with thread isolation.

例如,您可以设置/获取和更新它们,就像在 C 中处理变量一样。唯一添加的内容(以及由此而来的名称)是 the actual java objectvolatile 关键字。 .

这是为了防止 JVM 进行优化,并确保每次访问时都会读取该内存位置。来自 the JIRA ticket :

Clojure needs a faster variant of Atom for managing state inside transducers. That is, Atoms do the job, but they provide a little too much capability for the purposes of transducers. Specifically the compare and swap semantics of Atoms add too much overhead. Therefore, it was determined that a simple volatile ref type would work to ensure basic propagation of its value to other threads and reads of the latest write from any other thread. While updates are subject to race conditions, access is controlled by JVM guarantees.

Solution overview: Create a concrete type in Java, akin to clojure.lang.Box, but volatile inside supports IDeref, but not watches etc.

这意味着, volatile !仍然可以被多个线程访问(这对于转换器来说是必需的),但它不允许被这些线程更改同时,因为它不会为您提供原子更新。

volatile 的语义在a java answer中有很好的解释。 :

there are two aspects to thread safety: (1) execution control, and (2) memory visibility. The first has to do with controlling when code executes (including the order in which instructions are executed) and whether it can execute concurrently, and the second to do with when the effects in memory of what has been done are visible to other threads. Because each CPU has several levels of cache between it and main memory, threads running on different CPUs or cores can see "memory" differently at any given moment in time because threads are permitted to obtain and work on private copies of main memory.

现在让我们看看为什么不使用 var-settransients:

Volatile 与 var-set

Rich Hickey didn't want to give truly mutable variables :

Without mutable locals, people are forced to use recur, a functional looping construct. While this may seem strange at first, it is just as succinct as loops with mutation, and the resulting patterns can be reused elsewhere in Clojure, i.e. recur, reduce, alter, commute etc are all (logically) very similar. [...] In any case, Vars are available for use when appropriate.

从而创建with-local-varsvar-set等。这些问题的问题在于它们是真实 vars var-set 的文档字符串告诉您:

The var must be thread-locally bound.

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

为什么不使用 transient

Transients相似之处在于它们不允许并发访问并优化改变数据结构。问题是 transient 仅适用于实现 IEditableCollection 的集合。也就是说,它们只是为了避免集合数据结构的昂贵的中间表示。另请记住, transient 不会被敲击到位,您仍然需要一些内存位置来存储实际的 transient 。 volatile 通常用于简单地保存一个标志或最后一个元素的值(例如,请参见 partition-by)

摘要:

Volatile 只不过是 java volatile 的包装器,因此具有完全相同的语义。永远不要分享它们。请务必非常小心地使用它们。

关于clojure - Clojure volatile 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31288608/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com