【问题标题】:Java is the reference of the object stored in the cache or the object himself?Java是缓存中存储的对象的引用还是对象本身?
【发布时间】:2018-09-21 19:14:39
【问题描述】:

如果我有:

final Myobject o = new Myobject();

这是存储在堆中的。 出于性能原因,这也存储在使用它的本地处理器缓存中,我的问题是:多线程是否存在可见性问题?

2 种不同的场景:

1) 如果对象的整个结构都存储在缓存中,而其他线程对其进行了修改,是的,这应该是可见性问题。

2) 如果只有引用存储在缓存中,那么即使另一个线程修改它也不会有问题,因为每个线程都会从主内存/堆中读取。

我的推理对吗?

作为下一个问题,我想知道 java 在缓存中存储了什么,如果对象的整个结构从堆复制到缓存或仅引用,我在哪里可以找到这些信息?

谢谢:)

【问题讨论】:

  • 你说的是 CPU 缓存(L1、L2 等)吗?
  • "多线程是否存在可见性问题?"是的。
  • Java 内存模型定义了从多个线程访问数据存在哪些保证。如果您使用合适的锁定结构(等),那么这些问题没有实际意义。
  • 是的,如果我是对的,我认为它们是唯一的缓存
  • 另外值得注意的是,堆和缓存并不是不同的东西。堆是一种抽象,构建在虚拟内存中。这本身就是物理内存之上的抽象,其中的一部分在不同的时间被复制到不同的缓存中。

标签: java multithreading concurrency shared-memory heap-memory


【解决方案1】:

具有引用值的数据和对象的数据存储在内存中的两个不同位置。

对象的数据可能存储在内存中的多个位置,例如如果对象有String 字段,则String 对象本身就是两个对象(String 对象和带有文本的char[]),这意味着您的对象可能位于内存中的 3 个不同位置。

根据您对对象的引用,这意味着总共有 4 个不同的内存位置,仅针对具有 String 字段的简单对象。

这 4 个位置由 CPU 根据需要独立缓存

例如,如果你写o.getName().length(),它要求CPU:

  • 阅读参考资料
  • 读取Myobjectname 字段(String 参考)
  • 读取Stringvalue 字段(char[] 参考)
  • 阅读char[]length

所有 4 个内存位置都将加载到 CPU 缓存中。

一些内存位置可能彼此非常接近并且驻留在同一个内存块中,例如String 对象和char[] 可能彼此相邻,因此只需要加载 3 个内存,但上述操作可能会访问 4 个不同的内存块。

请注意,无论您的引用是在堆栈上(局部变量或参数)还是在堆上(另一个对象的字段),它仍然只是内存中的数据。

【讨论】:

    【解决方案2】:

    CPU 缓存的内容由 CPU 控制,即实际的硬件。它缓存任意内存内容,不区分引用或对象。

    因此,只要多个线程访问可变内存,就可能出现可见性问题。

    Java 保证方法中的局部变量只能由单个线程访问。也就是说,如果你这样做

    void someMethod() {
       final Myobject o = new Myobject();
       // do something with o
    }
    

    引用不会被共享,但对象可能会被共享(如果构造函数存储对对象的引用,另一个线程可能会看到它)。

    【讨论】:

      猜你喜欢
      • 2012-08-04
      • 2020-06-30
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      相关资源
      最近更新 更多