【问题标题】:What are the semantic implications of :volatile-mutable versus :unsynchronized-mutable?:volatile-mutable 与 :unsynchronized-mutable 的语义含义是什么?
【发布时间】:2014-01-15 01:43:46
【问题描述】:

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

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

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

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

谢谢!

【问题讨论】:

  • 这绝对是在说您应该使用可变字段。
  • 源示例的链接现已断开,但对于现在想知道警告来源的任何人,它位于deftype 的文档字符串中。

标签: clojure mutability


【解决方案1】:

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

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

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

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

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

如果这不是 100% 有意义,我很抱歉;语义复杂的;如果您想更深入地了解,请阅读此内容:When exactly do you use the volatile keyword in Java?

tldr;

易失性的性能略低于非同步;但它提供了更好的跨线程数据保证。

尽可能避免使用它们,但如果需要使用其中一个,您可能需要:volatile-mutable

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我认为它比“任何使用它们的人都应该知道其中的区别”更进一步。它确实这么说,但它也说它们仅用于构建更高级别的构造,在大多数情况下,即使对于那些确实了解这两种字段类型含义的人来说,这在我看来也是一种非常强烈的阻碍。
    【解决方案3】:

    意思是如果你不明白:volatile-mutable:unsynchronized-mutable 之间的区别,你应该使用Clojure 的引用类型而不是直接使用可变字段。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-14
      • 2011-02-25
      • 2019-12-18
      • 1970-01-01
      • 2020-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多