2014-08-28 55 views
3

在Java中,我如何能明确地触发一个完整的存储栅栏/屏障,等于的Java相当于Thread.MemoryBarrier

System.Threading.Thread.MemoryBarrier(); 

在C#中调用?

我知道,因为Java 5的读取和写入volatile变量已引起全的存储栅栏,但也许有没有volatile的(有效)的方式。

+0

在同一个对象上同步或从相同的易失性字段中读取。 – 2014-08-28 16:09:11

回答

3

相比MemoryBarrier(),Java的之前发生是一个非常尖锐的工具,留出更多余地积极的优化,同时保持线程安全。

正如您所期望的那样,更清晰的工具也需要更多的小心才能正确使用,这就是如何描述变量访问的语义。您必须在写入站点写入volatile变量,并在每个读取站点上从相同的易失性读取。通过暗示,您可以拥有任意数量的独立的本地化“内存障碍”,每个变量有一个,并且每个仅保护从该变量可到达的状态。

完整的习惯用法通常被称为“安全出版物”(尽管这是一个更为通用的术语),并且意味着填充将在线程之间共享的不可变对象图形,然后将其参考写入volatile变量。

+0

在写入站点上使用MemoryBarrier时,读取站点上可能的重新排序需要在C#中在读取站点上调用MemoryBarrier。因此,与Java中的MemoryBarrier相当的代码是下面的代码,还是因为优化而无法工作? 'public class Helper {private static volatile int a = 0; public static void MemoryBarrier(){int b = a; a = 0;是的,我认为这可以被认为是等价的(不允许优化一个易失性的读或写操作);}}' – ominug 2014-08-28 16:28:43

+0

不过,你最好把它分成读取和写入屏障。而且,最重要的是,您会更好地编写惯用的Java代码,而不是您提出的帮助程序类。 – 2014-08-28 16:34:12

0

没有直接的等价物。使用易变的领域或更高层次的东西。

+0

那么我应该用Java编写自己的帮助类吗? 'public class Helper {private static volatile int a = 0; public static void MemoryBarrier(){int b = a; }}' – ominug 2014-08-28 16:16:32

+0

你可以。但这不是个好主意,因为你的工作水平很低。最好使用高级别的东西来为你做这项工作。我试着解释一下例子。您使用内存屏障来保证变量(或几个)的写入和读取之间的可见性。但是最好直接通过手动将挥发性变量声明给变量声明来显示你的意图,并让Java为你做它,它可以移除样板代码,并且当你为代码添加对变量的新访问时,它可以帮助你不要忘记放置障碍。 – talex 2014-08-28 16:37:10

+0

而且你的帮手也是错的:) – talex 2014-08-28 16:39:16

2

Java 8,通过JEP 108增加了另一种可能性。对Java API,fullFence,loadFence和storeFence访问三个栅栏。