我知道在Java中使用volatile变量的目的是为了使对这些变量的写操作可以立即被其他线程看到。我也知道同步块的一个效果是将线程本地内存刷新到全局内存。
但我从来没有完全理解在这种情况下 'thread-local' 内存的引用。我知道仅存在于堆栈上的数据是线程本地的,但当涉及到堆上的对象时,我的理解就变得模糊了。
我希望能够得到以下几点的评论:
在多处理器机器上执行时,刷新线程本地内存是否只是指将CPU缓存刷新到RAM中?
在单处理器机器上执行时,这是否有任何意义?
如果堆可以在两个不同的内存位置具有相同的变量(每个位置由不同的线程访问),那么会在什么情况下出现这种情况?这对垃圾回收有什么影响?虚拟机对此类事情的处理方式是多么积极?
(编辑:添加问题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可以物理访问该内存,或者虚拟机是否进行逻辑线程本地堆分区?
任何演示文稿或文档的链接都将非常有帮助。我已经花费了时间研究这个问题,虽然我找到了很多好文献,但我还没有能够满足我的好奇心,了解线程本地内存的不同情况和定义。
非常感谢。
synchronized
表示“一切都要刷新”。synchronized
有一个参数,即获取锁的实例,但是 Java 内存模型规定线程的整个内存视图都受到内存屏障的影响。现在,如果 JVM 可以证明它不需要刷新对象,因为没有其他线程可能会看到它(而“未逃逸的对象”是很好的候选对象),那么 JVM 可以自由地不刷新,根据“好像”规则(只要结果与 Java 抽象机器无法区分,JVM 可以做任何它想做的事情)。 - Thomas Pornin