java - Java 内存模型 (JSR-133) 是否暗示进入监视器会刷新 CPU 数据缓存?

标签 java multithreading synchronization memory-model cpu-cache

Java 内存模型让我感到困扰(如果我理解正确的话)。如果有两个线程 A 和 B,则无法保证 B 会看到 A 写入的值,除非 A 和 B 在同一监视器上同步。

对于任何保证线程间缓存一致性的系统架构来说,都是没有问题的。但是如果架构不支持硬件缓存一致性,这实质上意味着每当线程进入监视器时,之前所做的所有内存更改都必须提交到主内存,并且缓存必须失效。它必须是整个数据缓存,而不仅仅是几行,因为监视器不知道它保护的内存中的哪些变量。 但这肯定会影响任何需要频繁同步的应用程序的性能(尤其是诸如具有短期运行作业的作业队列)。那么 Java 能否在没有硬件缓存一致性的架构上工作得相当好?如果不是,为什么内存模型不对可见性做出更强的保证?如果该语言需要监视器保护的信息,效率会不会更高?

正如我所见,内存模型给了我们两个世界中最糟糕的一面,即绝对需要同步,即使缓存一致性在硬件中得到保证,另一方面在不一致的架构(完全缓存刷新)上表现不佳。那么它不应该更严格(需要监视器保护的信息)或更多地丢失并将潜在平台限制为缓存一致的架构吗?

就目前而言,它对我来说意义不大。有人可以弄清楚为什么选择这个特定的内存模型吗?


编辑:回想起来,我对 strict 和 lose 的使用是一个糟糕的选择。我对保证较少的情况使用“严格”,对相反的情况使用“丢失”。为避免混淆,最好用更强或更弱的保证来说话。

最佳答案

the absolute need to synchronize, even if cache coherency is guaranteed in hardware

是的,但是你只需要针对 Java 内存模型进行推理,而不是针对你的程序恰好在其上运行的特定硬件架构。另外,这不仅与硬件有关,编译器和 JIT 本身也可能会重新排序导致可见性问题的指令。 Java 中的同步结构在所有可能的代码转换级别(例如编译器/JIT/CPU/缓存)一致地解决了可见性和原子性问题。

and on the other hand bad performance on incoherent architectures (full cache flushes)

也许我误解了 s/t,但是对于不连贯的架构,您无论如何都必须同步关键部分。否则,由于重新排序,您将遇到各种竞争条件。我不明白为什么 Java 内存模型会使事情变得更糟。

shouldn't it be more strict (require information what is guarded by a monitor)

我认为根本不可能告诉 CPU 刷新缓存的任何特定部分。编译器能做的最好的事情就是发出内存栅栏,让 CPU 决定缓存的哪些部分需要刷新——它仍然比我想的要粗粒度。即使可以进行更细粒度的控制,我认为这会使并发编程变得更加困难(已经够困难了)。

据我所知,Java 5 MM(就像 .NET CLR MM)比 x86 和 IA64 等常见架构的内存模型更“严格”。因此,它使关于它的推理相对简单。然而,它显然不应该提供更接近顺序一致性的 s/t,因为这会显着损害性能,因为可以应用更少的编译器/JIT/CPU/缓存优化。

关于java - Java 内存模型 (JSR-133) 是否暗示进入监视器会刷新 CPU 数据缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3054251/

相关文章:

java - Java中的优先级队列

python - 如何测试访问数据库的其他线程

ios - 如何使用 Dropbox Sync API 使目录及其内容保持同步?

java - 顺序和并行处理

java - 使用 android.gms.drive 从 android 中删除/垃圾文件

java - 不断收到 org.hibernate.exception.JDBCConnectionException : could not execute query

c++ - Qt 脚本多线程

java - 如何延迟 ScheduledExecutorService?

iphone - 当同步访问对象时,是什么导致对象 [0] 处出现 nil 对象?

java - 从一个文件中获取整数列表