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如何访问和写入内存可能是一个令人惊讶的复杂主题,因为它可能会对性能产生巨大影响。