【问题标题】:Does Java change the value of only the modified fields from cache?Java 是否仅更改缓存中已修改字段的值?
【发布时间】:2021-05-30 08:12:09
【问题描述】:

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

在此,我假设 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对此有任何保证吗?

假设没有建立之前/之后发生的关系。没有同步或易失性或任何其他类似的东西。

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

【问题讨论】:

    标签: java caching cpu cpu-cache


    【解决方案1】:

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

    您所指的问题称为单词撕裂,JVM 应该防止它。

    查看以下链接:

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

    【讨论】:

    • 当你说写不需要去主内存时,你的意思就像写回中发生的事情,意味着延迟写,等待那个特定的缓存块需要被驱逐,或者失效了吗?
    • 如果我们看Java,当一个线程完成执行时,缓存写入必须发生,对吧?还是没有任何保证?
    • 失效并不意味着需要将缓存行写入主内存。在下一个例子中假设 MESI。 CPU1 已经读取了一条缓存线(因此它处于共享状态),而 CPU2 想要写入相同的缓存线。写入核心将执行 RFO(所有权请求),这将使 CPU1 处的缓存行无效,并将其作为独占/修改后的 CPU2 公开。但是缓存行不需要写入主内存,因为它不是脏的。
    • 将更改写入内存是一种谬误。当需要写入主存时,由缓存一致性算法决定。写入主存是缓存一致性算法和资源量限制的产物。缓存是事实的来源。
    • 例如,使用 MESI 的系统需要将缓存线写回主内存,如果缓存线被修改并且不同的 CPU 想要读取它。但是 MESI 的一个改进是 MOESI,可以共享脏缓存线(它处于 OWNED 状态),而无需将其写入主内存。所以写入主存只是算法和可用资源量的产物。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    相关资源
    最近更新 更多