2011-05-03 68 views
0

幾天前,我提出了一個問題,問如何使用關鍵字'volatile'並且我得到了答案。在此我要再次感謝幫助我的人們。 然而,在我腦海中出現了一個關於JMM的新問題,那就是目前我知道有主存和線程自己單獨的緩存(可能有更多專業術語),現在我想知道線程緩存中存儲了什麼,共享對象引用的副本(對象地址的副本)還是共享對象的副本?例如,我聲明一個對象B b = new B();和b可以通過然後兩個線程進行訪問時B由線程訪問是對象參考 b的複製並存儲在線程自己的高速緩衝存儲器或爲對象其中B點被複制並存儲在線程自己的高速緩存記憶?謝謝。關於Java內存模型的問題

回答

3

任何被多個線程訪問的東西都可以在「線程緩存」中。如果它們是對象的一部分,則包括引用。它不包含保存在本地變量中的引用,因爲它們在堆棧上,不能從其他線程訪問。

所以答案是真的「兩個」。

+0

不能很好理解,請看下面的例子代碼:'public class Test { \t \t public B b = new B(); \t \t 公共靜態無效的主要(字串[] args){ \t \t新線程(){ \t \t \t公共無效的run(){ \t \t \t \t b.setName( 「測試1」); \t \t \t} \t \t} .start(); //線程1 \t \t \t \t新的Thread(){ \t \t \t公共無效的run(){ \t \t \t \t灣的setName( 「test2的」); \t \t \t} \t \t} .start(); // thread 2 \t} }'當thread1和thread2訪問b時,它們是否緩存引用b的副本和對象的副本?那麼複製b參考指向複製對象而不是原始對象? – 2011-05-03 05:30:08

+0

是的,「b」字段和「b」引用的對象中的數據都可以在每個CPU的緩存中(沒有像每個線程緩存那樣的東西)。當JVM需要通過CPU高速緩存進行讀取或寫入時,synchronized,volatile和final關鍵字控制。 – 2011-05-03 05:43:12

+0

謝謝大家。只是仍然是相同的代碼示例。如果我在thread1中調用「b = null」,那麼在被訪問時,b在thread2中可能不爲null,因爲b沒有被聲明爲'volatile',對吧?如果我在thread1中調用「b.setName(」test1「)」,那麼thread2中b.getName()的返回值可能不是「test1」,如果在B類中沒有聲明爲'volatile',對吧?謝謝。 – 2011-05-03 08:13:31

0

變量b是對象的引用,它存儲在堆中。

0

通常,您不需要知道存儲參考的時間或地點。記憶不僅僅是兩層,它比那更復雜。從上到下你有。

registers 
L1 cache 
L2 cache 
L3 cache 
local main memory 
nonlocal main memory 
swap space. 

本地主內存是本地CPU的內存。你可以有另一個CPU的本地內存。因此,要執行

B b = new B(); 

它分配通常來自TLAB一些內存(線程本地分配緩衝區)這個內存空間通常是在某處本地主內存之間的L1。可以在各級複製。然而,參考必須位於寄存器中,因此可以將其分配給局部變量。它可能被保存到堆棧和內存中,或者可能不會。

即使在CPU中,「寄存器」也是一個廣泛的類別。 CPU如何訪問和寫入內存可能是一個令人驚訝的複雜主題,因爲它可能會對性能產生巨大影響。