【问题标题】:Java seems to support volatile fields of type long, while C# does not - What are the reasons behind this?Java 似乎支持 long 类型的 volatile 字段,而 C# 不支持 - 这背后的原因是什么?
【发布时间】:2010-11-01 07:32:20
【问题描述】:

谁能向我解释这两种不同方法的优缺点是什么?

【问题讨论】:

    标签: c# java multithreading volatile


    【解决方案1】:

    当 Java 中的 doublelongvolatile 时,§17.7 of the Java Language Specification 要求以原子方式读写它们。当它们不是易失性的时,它们可以被写入多个操作中。例如,这可能导致 long 的高 32 位包含新值,而低 32 位仍包含旧值。

    对于程序员来说,原子读写更容易推理和编写正确的代码。但是,在某些环境中,对原子操作的支持可能会给 VM 实现者带来负担。

    【讨论】:

      【解决方案2】:

      我不知道为什么 volatile 在 C# 中不能应用于 64 位整数,但是您可以使用 Thread.VolatileWrite 在 C# 中做您想做的事情。 volatile 关键字只是此调用的语法糖。

      摘录:

      注意: 在 C# 中,在字段上使用 volatile 修饰符可确保对该字段的所有访问 使用 Thread.VolatileRead 或 Thread.VolatileWrite。

      语法糖(关键字)适用于 32 位整数,但您可以在 64 位整数上使用实际的方法调用。

      【讨论】:

        【解决方案3】:

        我想这取决于内存模型可以保证什么。我不太了解 CLI 内存模型(C# 必须使用),但我知道它会保证 32 位......但不是 64 位(尽管它会保证 x64 上的 64 位引用 -完整的规则在 ECMA 334v4 的 §17.4.3) 中。所以不能是volatile。不过,您仍然拥有Interlocked 方法(例如long Interlocked.Exchange(ref long,long)long Interlocked.Increment(ref long) 等)。

        【讨论】:

        • 不过,当您还将平台指定为 x64 时,代码不允许您指定 volatile 64 位字段,这很奇怪。
        • 无论底层平台如何,CLI 都应该可以工作,因此它不希望做出取决于您运行的内容的承诺。
        【解决方案4】:

        我猜测 long 在 C# 中不会是 volatile 的,因为它们大于 32 位并且不能在原子操作中访问。即使它们不会存储在寄存器或 CPU 缓存中,因为读取或写入值需要多个操作,所以一个线程可能读取该值,而另一个线程正在写入它。

        我认为 Java 实现 volatile 字段的方式与 DotNet 的方式之间存在差异,但我不确定细节。 Java 可能会使用字段锁定来防止出现 C# 的问题。

        【讨论】:

          猜你喜欢
          • 2020-07-17
          • 1970-01-01
          • 2021-07-06
          • 1970-01-01
          • 1970-01-01
          • 2012-02-01
          • 1970-01-01
          • 2013-01-04
          相关资源
          最近更新 更多