将线程本地内存刷新到全局内存是什么意思? [英] What does flushing thread local memory to global memory mean?

查看:20
本文介绍了将线程本地内存刷新到全局内存是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 Java 中 volatile 变量的目的是写入此类变量对其他线程立即可见.我也知道同步块的作用之一是将线程本地内存刷新到全局内存.

I am aware that the purpose of volatile variables in Java is that writes to such variables are immediately visible to other threads. I am also aware that one of the effects of a synchronized block is to flush thread-local memory to global memory.

在这种情况下,我从未完全理解对线程本地"内存的引用.我知道只存在于堆栈上的数据是线程本地的,但是当谈到堆上的对象时,我的理解变得模糊.

I have never fully understood the references to 'thread-local' memory in this context. I understand that data which only exists on the stack is thread-local, but when talking about objects on the heap my understanding becomes hazy.

我希望能得到以下几点评论:

I was hoping that to get comments on the following points:

  1. 在具有多个处理器的机器上执行时,刷新线程本地内存是否只是指将 CPU 缓存刷新到 RAM 中?

  1. When executing on a machine with multiple processors, does flushing thread-local memory simply refer to the flushing of the CPU cache into RAM?

在单处理器机器上执行时,这有什么意义吗?

When executing on a uniprocessor machine, does this mean anything at all?

如果堆可以在两个不同的内存位置(每个由不同的线程访问)有相同的变量,在什么情况下会出现这种情况?这对垃圾收集有什么影响?虚拟机做这种事情的积极性如何?

If it is possible for the heap to have the same variable at two different memory locations (each accessed by a different thread), under what circumstances would this arise? What implications does this have to garbage collection? How aggressively do VMs do this kind of thing?

(添加问题 4) 退出同步块时刷新哪些数据?它是线程在本地拥有的一切吗?是否仅在同步块内进行了写入?

( adding question 4) What data is flushed when exiting a synchronized block? Is it everything that the thread has locally? Is it only writes that were made inside the synchronized block?

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 完成逻辑线程本地堆分区?

Overall, I think am trying to understand whether thread-local means memory that is physically accessible by only one CPU or if there is logical thread-local heap partitioning done by the VM?

任何指向演示文稿或文档的链接都会非常有帮助.我花了时间研究这个,虽然我找到了很多不错的文献,但我一直无法满足我对不同情况的好奇心&线程本地内存的定义.

Any links to presentations or documentation would be immensely helpful. I have spent time researching this, and although I have found lots of nice literature, I haven't been able to satisfy my curiosity regarding the different situations & definitions of thread-local memory.

非常感谢.

推荐答案

您所说的刷新被称为内存屏障".这意味着 CPU 确保它看到的 RAM 也可以从其他 CPU/内核查看.这意味着两件事:

The flush you are talking about is known as a "memory barrier". It means that the CPU makes sure that what it sees of the RAM is also viewable from other CPU/cores. It implies two things:

  • JIT 编译器刷新 CPU 寄存器.通常,代码可能会在 CPU 寄存器中保留一些全局可见数据(例如实例字段内容)的副本.其他线程无法看到寄存器.因此,synchronized 的一半工作是确保不维护此类缓存.

  • The JIT compiler flushes the CPU registers. Normally, the code may kept a copy of some globally visible data (e.g. instance field contents) in CPU registers. Registers cannot be seen from other threads. Thus, half the work of synchronized is to make sure that no such cache is maintained.

synchronized 实现还执行内存屏障,以确保从当前内核对 RAM 的所有更改都传播到主 RAM(或者至少所有其他内核都知道这个核心有最新的值——缓存一致性协议可能非常复杂).

The synchronized implementation also performs a memory barrier to make sure that all the changes to RAM from the current core are propagated to main RAM (or that at least all other cores are aware that this core has the latest values -- cache coherency protocols can be quite complex).

第二项工作在单处理器系统(我的意思是,具有单核的单 CPU 的系统)上是微不足道的,但如今单处理器系统往往变得越来越少.

The second job is trivial on uniprocessor systems (I mean, systems with a single CPU which has as single core) but uniprocessor systems tend to become rarer nowadays.

对于线程局部堆,理论上可以这样做,但通常不值得付出努力,因为没有任何内容可以说明要使用同步刷新内存的哪些部分.这是线程共享内存模型的一个限制:所有 内存应该是共享的.在第一次遇到 synchronized 时,JVM 应该将其所有线程本地堆对象"刷新到主 RAM.

As for thread-local heaps, this can theoretically be done, but it is usually not worth the effort because nothing tells what parts of the memory are to be flushed with a synchronized. This is a limitation of the threads-with-shared-memory model: all memory is supposed to be shared. At the first encountered synchronized, the JVM should then flush all its "thread-local heap objects" to the main RAM.

但是最近来自 Sun 的 JVM 可以执行逃逸分析",其中 JVM 成功地证明某些实例永远不会从其他线程可见.这是典型的,例如,由 javac 创建的 StringBuilder 实例来处理字符串的连接.如果实例从未作为参数传递给其他方法,则它不会成为全局可见".这使它有资格进行线程本地堆分配,甚至在适当的情况下,也适用于基于堆栈的分配.请注意,在这种情况下没有重复;该实例不在同时在两个地方".只是JVM可以将实例保存在一个私有的地方,不会产生内存屏障的成本.

Yet recent JVM from Sun can perform an "escape analysis" in which a JVM succeeds in proving that some instances never become visible from other threads. This is typical of, for instance, StringBuilder instances created by javac to handle concatenation of strings. If the instance is never passed as parameter to other methods then it does not become "globally visible". This makes it eligible for a thread-local heap allocation, or even, under the right circumstances, for stack-based allocation. Note that in this situation there is no duplication; the instance is not in "two places at the same time". It is only that the JVM can keep the instance in a private place which does not incur the cost of a memory barrier.

这篇关于将线程本地内存刷新到全局内存是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆