7

当我注意到一个可变字段用^:unsynchronized-mutable注释时,我正在研究一个 clojure 库。Mutable 是可变的,但我不知道非同步部分是什么意思,所以我阅读了文档,其中包含:

请注意,可变字段极难正确使用,并且仅用于促进在 Clojure 本身中构建更高级别的构造,例如 Clojure 的引用类型。它们仅供专家使用 - 如果 :volatile-mutable 或 :unsynchronized-mutable 的语义和含义对您来说不是很明显,那么您不应该使用它们。

我无法理解细微差别:是说在实践中我选择哪种可变性注释并不重要,还是人们应该完全忘记使用可变类型?

而且,为了好奇,在较低的抽象层次上,它们之间的语义区别是什么?

谢谢!

4

3 回答 3

3

这些是 java 结构,这就是为什么在 clojure 文档中除了“不要使用它”之外的任何地方都看不到它们的原因。

对于声明为“volatile”的所有变量,读取和写入都是原子的。

非同步字段是常规的 Java 可变字段。

请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

实际上,这意味着如果你有一个数据结构,当多个线程访问数据以进行读取或写入volatile目标时,将始终保持一致;也就是说,您将始终获得一个完全在对该数据进行操作之前或完全来自之后的数据对象。

如果这没有 100% 的意义,我很抱歉;语义复杂;如果您想更深入地了解,请阅读以下内容:您究竟何时在 Java 中使用 volatile 关键字?

tldr;

Volatile 的性能比 unsynchronized 稍差;但它提供了更好的跨线程数据保证。

如果可以的话,避免它们,但如果你需要使用一个,你可能想要:volatile-mutable

于 2016-05-14T04:24:43.217 回答
2

好吧,这并不是说“人们”应该忘记使用可变类型。它的意思是任何使用它们的人都应该知道 unsynchronized 和 volatile 之间的区别(并暗示这不是 Clojure 特定的问题,否则将在文档字符串中解释)。我不知道一个明确的解释,但在使用 Clojure 的可变 deftype 字段之前,您应该了解 java 内存模型,以及一般的线程和同步。

我手头没有明确的参考资料,但 Wikipedia 似乎有一篇关于该主题的有用文章(nb 我刚刚找到它,只是略读了一下)。

于 2014-01-15T08:51:26.137 回答
1

就是说如果你不理解 和 之间的区别:volatile-mutable:unsynchronized-mutable你应该使用 Clojure 的引用类型,而不是直接使用可变字段。

这两种可变性有不同的策略来保证共享可变数据的线程之间的一致性,这会导致读/写操作的性能不同。有时,您可以通过微调特定类型的可变性来获得更好的性能。如果您天真地使用它们,您可能会变得奇怪且难以理解错误。

于 2014-01-15T17:06:38.673 回答