我知道,Java中volatile变量的用途是写入这些变量对其他线程立即可见。我也意识到一个同步块的效果之一就是将线程本地内存刷新到全局内存。刷新线程局部内存到全局内存是什么意思?
我从来没有完全理解在这种情况下对'线程本地'内存的引用。我明白,只存在于堆栈上的数据是线程本地的,但是当谈论堆中的对象时,我的理解变得朦胧。
我希望得到以下几点意见:
当一台机器上有多个处理器上执行,并刷新线程本地存储仅仅指的是CPU缓存到内存的冲洗?
在单处理器机器上执行时,这是否意味着什么?
如果堆有可能在两个不同的内存位置(每个都由不同的线程访问)有相同的变量,在什么情况下会出现这种情况?这对垃圾收集有什么影响?虚拟机如何积极地做这种事情?
(编辑:添加问题4)退出同步块时刷新了什么数据?这是线程在本地的一切吗?它只是在同步块内写入的吗?
Object x = goGetXFromHeap(); // x.f is 1 here Object y = goGetYFromHeap(); // y.f is 11 here Object z = goGetZFromHead(); // z.f is 111 here y.f = 12; synchronized(x) { x.f = 2; z.f = 112; } // will only x be flushed on exit of the block? // will the update to y get flushed? // will the update to z get flushed?
总的来说,我认为想了解是否线程局部手段内存只有一个CPU物理访问或者如果由VM进行逻辑线程本地堆分配?
任何指向演示或文档的链接都将非常有帮助。我花了很多时间研究这个问题,虽然我发现了很多很好的文献,但我一直无法满足我对线程本地存储器的不同情况定义的好奇心。
非常感谢。
感谢您的意见。我其实很熟悉逃生分析,它开始与'线程本地'混淆。我想请问两个后续问题: 1.如果编译器已经证明一个对象是线程本地的,并且该对象存在于堆的线程局部区域中,那么为什么要写入该对象内部一个同步块需要刷新?从CPU缓存到线程本地堆区域的刷新只能被写入的线程观察到?这是线程切换处理器,并开始执行一个不同的CPU缓存? – 2010-03-22 21:32:47
2. JVM有可能在堆上的两个单独的内存位置同时存在一个对象吗?如果是这样,在什么情况下会出现这种情况? – 2010-03-22 21:33:22
1.“同步”意味着“全部”的冲洗。 'synchronized'有一个参数,这个参数是获取锁的实例,但是Java内存模型要求来自线程的整个内存视图受到内存障碍的限制。现在,如果JVM可以证明它不需要刷新对象,因为没有其他线程可以看到它(并且“未转义对象”是很好的候选对象),那么JVM就可以在“as if”规则(JVM只要结果与Java抽象机器无法区分就可以完成它所希望的任何事情)。 – 2010-03-23 12:16:14