当前位置: 首页 > 面试题库 >

将线程本地内存刷新到全局内存是什么意思?

茹建茗
2023-03-14
问题内容

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

在这种情况下,我从未完全理解对“线程本地”内存的引用。我了解仅存在于堆栈中的数据是线程局部的,但是当谈论堆上的对象时,我的理解变得模糊。

我希望能就以下几点发表评论:

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

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

  3. 如果堆有可能在两个不同的内存位置(每个线程由不同的线程访问)具有相同的变量,那么在什么情况下会出现这种情况?这对垃圾回收有什么影响?VM如何积极地执行此类操作?

  4. (编辑:添加问题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进行了逻辑线程本地堆分区?

到演示文稿或文档的任何链接都将非常有帮助。我花了很多时间研究这个问题,尽管我找到了很多不错的文献,但是我对不同的情况和线程本地内存的定义无法满足我的好奇心。

非常感谢。


问题答案:

您所说的同花大顺被称为“内存屏障”。这意味着CPU确保从其他CPU /内核也可以看到RAM的内容。它意味着两件事:

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

  • synchronized实现还执行内存屏障,以确保将当前内核对RAM的所有更改都传播到主RAM(或者至少所有其他内核都知道该内核具有最新值-缓存一致性协议可以是复杂)。

在单处理器系统(我的意思是,具有单个CPU且具有单核的系统)上,第二项工作是微不足道的,但是单处理器系统在当今变得越来越罕见。

对于线程局部堆,理论上可以做到这一点,但是通常不值得付出努力,因为没有任何东西可以告诉您要使用a刷新内存的哪些部分synchronized。这是带共享内存的线程模型的局限性:应该共享
所有 内存。第一次遇到synchronizedJVM时,应将其所有“线程本地堆对象”刷新到主RAM。

但是,Sun最近提供的JVM可以执行“转义分析”,其中JVM成功地证明了某些实例永远不会从其他线程中看到。例如,这是StringBuilder创建javac用于处理字符串串联的实例的典型方法。如果实例从不作为参数传递给其他方法,则它不会变为“全局可见”。这使它有资格进行线程本地堆分配,甚至在适当的情况下也有资格进行基于堆栈的分配。请注意,在这种情况下,没有重复。该实例不在“同时位于两个地方”。只是JVM可以将实例保留在私有位置,而不会产生内存屏障的成本。



 类似资料:
  • 问题内容: 在多个帖子中都提到了这一点:不当使用会导致内存泄漏。我正在努力了解使用内存泄漏将如何发生。 我发现的唯一情况如下: Web服务器维护一个线程池(例如,用于servlet)。如果未删除其中的变量,则这些线程可能会导致内存泄漏,因为线程不会死亡。 这种情况下没有提到“ Perm Space”内存泄漏。那是内存泄漏的唯一(主要)用例吗? 问题答案: PermGen的exhaustions 与

  • 本文向大家介绍什么是内存泄漏?相关面试题,主要包含被问及什么是内存泄漏?时的应答技巧和注意事项,需要的朋友参考一下 答:一般我们所说的内存泄漏指的是堆内存的泄漏。堆内存是程序从堆中为其分配的,大小任意的,使用完后要显示释放内存。当应用程序用关键字new等创建对象时,就从堆中为它分配一块内存,使用完后程序调用free或者delete释放该内存,否则就说该内存就不能被使用,我们就说该内存被泄漏了。

  • 问题内容: 这个问题仅涉及内存可见性,而不是发生在之前和之后。Java中有四种方法可以保证一个线程中的内存更改对另一线程可见。(参考http://gee.cs.oswego.edu/dl/cpj/jmm.html) 写入线程释放同步锁,而读取线程随后获取该相同的同步锁。 如果将一个字段声明为易失性字段,则在写入线程执行任何进一步的内存操作之前,写入该线程的任何值都会被写入线程并使写入线程可见(即,

  • 虚拟机: 4CPU 10GB RAM 10GB交换 Java1.7-Xms=-Xmx=6144m Tomcat 7 我们观察到JVM有一种非常奇怪的行为。JVm驻留内存开始收缩,交换使用率飙升至50%以上。 请参阅下面来自监控工具的统计数据。 http://i44.tinypic.com/206n6sp.jpg http://i44.tinypic.com/m99hl0.jpg 任何能理解这一点的

  • 我是一个新的spark框架,我想知道什么是驱动内存和执行器内存?从两者中获得最大性能的有效方法是什么?

  • 为什么会这样?最后,还有其他类似的功能我应该知道是不允许的。