Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java似乎支持long类型的易失性字段,而C#不支持-这背后的原因是什么?_C#_Java_Multithreading_Volatile - Fatal编程技术网

Java似乎支持long类型的易失性字段,而C#不支持-这背后的原因是什么?

Java似乎支持long类型的易失性字段,而C#不支持-这背后的原因是什么?,c#,java,multithreading,volatile,C#,Java,Multithreading,Volatile,有人能给我解释一下这两种不同方法的优缺点吗?我想这可以归结为内存模型能保证什么。我对CLI内存模型(C#必须使用)了解得不多,但我知道它可以保证32位。。。但不是64位(尽管它将保证x64上的64位引用-完整规则见ECMA 334v4的§17.4.3)。所以它不可能是易变的。您仍然有联锁的方法(例如长联锁的.Exchange(ref long,long)和长联锁的.Increment(ref long)等)。我猜long在C中不可能是易变的,因为它们大于32位,在原子操作中无法访问。尽管它们不会

有人能给我解释一下这两种不同方法的优缺点吗?

我想这可以归结为内存模型能保证什么。我对CLI内存模型(C#必须使用)了解得不多,但我知道它可以保证32位。。。但不是64位(尽管它将保证x64上的64位引用-完整规则见ECMA 334v4的§17.4.3)。所以它不可能是易变的。您仍然有
联锁的
方法(例如
长联锁的.Exchange(ref long,long)
长联锁的.Increment(ref long)
等)。

我猜long在C中不可能是易变的,因为它们大于32位,在原子操作中无法访问。尽管它们不会存储在寄存器或CPU缓存中,但由于读取或写入值需要多个操作,因此一个线程可能在另一个线程写入值的过程中读取该值


我相信Java实现volatile字段的方式和DotNet实现volatile字段的方式是不同的,但我不确定具体细节。Java可能会在字段上使用一个锁来防止C出现问题。

当Java中的
double
long
易变时,需要以原子方式读写它们。当它们不是易失性时,可以在多个操作中写入它们。例如,这可能导致long的高32位包含新值,而低32位仍然包含旧值


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

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

摘录:

注: 在C#中,对字段使用volatile修饰符可以保证所有对该字段的访问 使用Thread.volatireRead或Thread.volatireWrite


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

不过,奇怪的是,当您还将平台指定为x64时,代码不允许您指定易失性64位字段。CLI应该可以工作,无论底层平台是什么,所以,它不想做出依赖于你所追求的东西的承诺。