简体   繁体   English

Java似乎支持long类型的volatile字段,而C#没有 - 这背后的原因是什么?

[英]Java seems to support volatile fields of type long, while C# does not - What are the reasons behind this?

任何人都可以向我解释这两种不同方法的优点和缺点是什么?

When a double or long in Java is volatile , §17.7 of the Java Language Specification requires that they are read and written atomically. 当Java中的doublelongvolatileJava语言规范的第17.7节要求以原子方式读取和写入它们。 When they are not volatile, they can be written in multiple operations. 当它们不易变时,它们可以用多个操作编写。 This can result, for example, in the upper 32 bits of a long containing a new value, while the lower 32 bits still contain the old value. 例如,这可能导致包含新值的long的高32位,而低32位仍然包含旧值。

Atomic reads and writes are easier for a programmer to reason about and write correct code with. 原子读写更容易让程序员推理和编写正确的代码。 However, support for atomic operations might impose a burden on VM implementers in some environments. 但是,在某些环境中,对原子操作的支持可能会给VM实施者带来负担。

I don't know the reason why volatile cannot be applied to 64-bit ints in C#, but You can use Thread.VolatileWrite to do what you want in C#. 我不知道为什么volatile不能在C#中应用于64位整数,但你可以使用Thread.VolatileWrite在C#中做你想做的事情。 The volatile keyword is just syntactic sugar on this call. volatile关键字只是这次调用的语法糖。

excerpt: 摘抄:

Note: In C#, using the volatile modifier on a field guarantees that all access to that field uses Thread.VolatileRead or Thread.VolatileWrite. 注意:在C#中,在字段上使用volatile修饰符可确保对该字段的所有访问都使用Thread.VolatileRead或Thread.VolatileWrite。

The syntactic sugar (keyword) applies to 32-bit ints, but you can use the actual method calls on 64-bit ints. 语法糖(关键字)适用于32位整数,但您可以使用64位整数的实际方法调用。

I guess it comes down to what the memory model can guarantee. 我想这归结为内存模型可以保证的。 I don't know a vast amount about the CLI memory model (that C# has to use), but I know it'll guarantee 32 bits... but not 64 (although it'll guarantee a 64-bit reference on x64 - the full rules are in §17.4.3 of ECMA 334v4) . 我不太了解CLI内存模型(C#必须使用),但我知道它将保证32位......但不是64位(虽然它可以保证x64上的64位引用 - 完整规则在ECMA 334v4的第17.4.3节中。 So it can't be volatile . 所以它不可能是volatile You still have the Interlocked methods, though (such as long Interlocked.Exchange(ref long,long) and long Interlocked.Increment(ref long) etc). 但是你仍然有Interlocked方法(例如long Interlocked.Exchange(ref long,long)long Interlocked.Increment(ref long)等)。

I'm guessing that longs can't be volatile in C# because they are larger than 32-bits and can not be accessed in an atomic operation. 我猜测long在C#中不能是volatile,因为它们大于32位且无法在原子操作中访问。 Even though they would not be stored in a register or CPU cache, because it takes more than one operation to read or write the value it is possible for one thread to read the value while another is in the process of writing it. 即使它们不会存储在寄存器或CPU缓存中,因为读取或写入值需要多个操作,一个线程可以读取该值,而另一个线程正在编写该值。

I believe that there is a difference between how Java implements volatile fields and how DotNet does, but I'm not sure on the details. 我相信Java实现volatile字段的方式和DotNet的工作方式之间存在差异,但我不确定细节。 Java might use a lock on the field to prevent the problem that C# has. Java可能会对字段使用锁定来防止C#具有的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM