Java 是否仅更改缓存中已修改字段的值?

时间:2021-02-28 16:36:30

标签: java caching cpu cpu-cache

根据我的理解,当发生从缓存到主存的回写时,它会写整个缓存块。这可能包括未修改的字节/字,因为脏位设置在整个缓存块上。

在这里,我假设 CPU 架构通常不会在字节级别跟踪“脏”。如果所有目前的架构都在字节级别进行跟踪,请随时纠正我的假设。

比如说,两个 java 字段,比如说 ab 并排存在并且具有相同的标签。因此,在缓存时,它们会被放置在同一个缓存块中。

假设有一个线程在内核中运行,它只更新 a 的值,而不更新 b 的值。那么,ab 的值实际上会在主内存中从缓存中更新吗? 或者java有什么东西可以确保只有a的值被更新,因为只有a被改变了?

java 在这里也有作用吗?还是完全依赖于CPU架构?

我真正关心的

假设最初,a=1b=1 假设我们有两个线程 T1 和 T2。 T1 只做一件事,它设置 a=2。类似地,T2 执行 b=2

假设我们有一个多核环境,内核 C1 和 C2 分别运行 T1 和 T2。两者都缓存值 a=1, b=1

说 T1 先完成。 C1 的缓存被写回。 所以,现在,在主存储器中,a=2, b=1。 现在,T2 结束。现在当缓存被写回时,它是否设置了 a=1, b=2 因为 C2 在它的缓存中有 a=1

或者Java对此有任何保证吗?

假设没有 Happens Before/After 关系建立。没有同步或易失性或任何其他类似的东西。

请随时纠正我的任何假设。

1 个答案:

答案 0 :(得分:1)

吹毛求疵:理论上写入不需要到主存;根据使用的缓存一致性算法,它们可以无限期地留在缓存中。

您所指的问题称为单词撕裂,JVM 应防止出现这种情况。

查看以下链接:

我不熟悉其他架构,但在 X86 上加载和存储可以在字节级别完成。一个 n 字节的字段,将始终是 n 字节对齐的;所以它永远不会被分成 2 个缓存行。由于 Java 中的布尔值存储在一个字节中,因此 X86 上不会发生字撕裂。