3

我需要一些幫助理解Java內存model.The下面是一個例子gerneric掌握基本概念:的Java happend,前同步塊

圖片我有一個對象實例調用Shared和兩個線程AB 。此外還有某種Queue,帶有同步的puttake

螺紋A修改前的Shared -instance put方法。

問題1:A所有變化是顯而易見的,當B通過同步take - 方法得到Shared -object實例?

問題2:只要A離開同步put-方法,刷新內存緩存(在Shared上的所有更改都可見)。如果在put中調用wait()-方法A,會發生什麼情況?即使A尚未退出​​-method,B也會看到對Shared所做的更改嗎?致電wait()時,緩存是否也會被刷新?

+0

非常混亂的問題。也許一些代碼樣例。例如,隊列如何更改put方法中的傳遞對象? – vidstige

回答

4

答案1:是的。因爲take()和put()都是同步的。因此,在B可以執行take()之前,A應該已經離開同步塊,並且離開同步塊意味着刷新內存緩存(內存圍欄/屏障)。

答案2:是的。因爲當調用wait()時,線程必須交出鎖,這將再次導致內存刷新。

編輯:我認爲你在之後是否緩存寫入內存發生在同步塊退出或釋放鎖定。答案是緩存寫入內存發生鎖的發佈。

2

您的第一個問題的答案是肯定的,因爲同步點(出現在put和take中)引入了隱式內存限制。

對於第二個問題,它取決於在對象添加到Shared之前或之後A調用等待。如果是以前的話,顯然沒有共享的變化,所以B沒有什麼新東西可以看到。

編輯:如果A調用之後等待,則更改是可見的,因爲您必須在添加之前獲取一個鎖,然後在等待時釋放它,這也引入了一個fence。

所以在這兩種情況下答案都是肯定的。

+0

謝謝,首先更改共享,然後調用wait()。它調用Queue-instance上的等待。我只是不確定是否將調用等待視爲「退出同步塊」。因爲只有退出同步塊時才保證內存刷新。瞭解我後? :-) –

+0

@Franz Kafka:我做了一個編輯。 – Tudor

2

A還沒有退出同步方法嗎?調用wait()時緩存是否也刷新?

報價從JSR 133 (Java Memory Model) FAQ - What does synchronization do?

後,我們退出synchronized塊,我們發佈的監測,其中有刷新緩存,主存儲器的作用,使該線程做寫入能對其他線程可見。在我們輸入一個同步塊之前,我們需要獲取監視器,這會導致本地處理器緩存失效,從而使變量從主內存中重新加載。然後,我們將能夠看到之前版本中可見的所有寫入。

它說沖洗緩存內存發生在監視器被釋放時。請注意,雖然監視器在退出同步塊時被釋放,但在調用等待方法時它也會被釋放。所以我期望在#wait()調用中刷新這些更改,並在其他線程提供它的時候提供它,以便它在更早的時候在同一臺顯示器上等待。