如何解决Java 是否仅更改缓存中已修改字段的值?
根据我的理解,当发生从缓存到主存的回写时,它会写整个缓存块。这可能包括未修改的字节/字,因为脏位设置在整个缓存块上。
在这里,我假设 cpu 架构通常不会在字节级别跟踪“脏”。如果所有目前的架构都在字节级别进行跟踪,请随时纠正我的假设。
比如说,两个 java 字段,比如说 a
和 b
并排存在并且具有相同的标签。因此,在缓存时,它们会被放置在同一个缓存块中。
假设有一个线程在内核中运行,它只更新 a
的值,而不更新 b
的值。那么,a
和 b
的值实际上会在主内存中从缓存中更新吗?
或者java有什么东西可以确保只有a
的值被更新,因为只有a
被改变了?
我真正关心的
假设最初,a=1
,b=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 关系建立。没有同步或易失性或任何其他类似的东西。
请随时纠正我的任何假设。
解决方法
吹毛求疵:理论上写入不需要到主存;根据使用的缓存一致性算法,它们可以无限期地留在缓存中。
您所指的问题称为单词撕裂,JVM 应防止出现这种情况。
查看以下链接:
- https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.6
- https://shipilev.net/blog/2014/jmm-pragmatics/#_part_ii_word_tearing
我不熟悉其他架构,但在 X86 上加载和存储可以在字节级别完成。一个 n 字节的字段,将始终是 n 字节对齐的;所以它永远不会被分成 2 个缓存行。由于 Java 中的布尔值存储在一个字节中,因此 X86 上不会发生字撕裂。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。