2014-08-28 38 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訪問三個柵欄。