在Java中,如何刷新CPU内存缓存以便从RAM内存中检索最新内存?

时间:2012-03-06 11:07:21

标签: java concurrency volatile synchronized

计算机具有RAM内存,但它也具有小巧,快速的CPU内存缓存。 Java内存模型保证在访问具有volatile的变量时刷新CPU内存缓存,但由于我们仅在单个线程中的单个类中使用该volatile变量,因此不确定JIT是否只是优化它。

要诊断一个错误(当我们在特定点调用Thread.sleep()足够长时才会出现这个错误),我们需要能够做这样的事情(而不是sleep()):

System.clearCpuCache();

实现这种方法的最简单,最可靠的方法是什么?它应该保证它不会JIT优化缓存刷新。 我们只能在启用JIT的情况下重现我们的错误,因此禁用JIT不是一种选择。

4 个答案:

答案 0 :(得分:8)

你通常不能。除性能外,缓存的存在对应用程序是透明的。这也适用于多处理器系统,只要缓存系统是“缓存一致”,这几乎是当今使用的所有平台。

因此,你的错误在其他地方。

易失性和同步块之类的东西本身不会影响缓存一致性,而是寄存器优化,使用原子指令(包括刷新存储缓冲区,这与缓存不同!),以及等等。这些是你应该看的东西(好吧,鉴于你的描述中缺乏细节,很难说,但作为第一个猜测..),而不是试图刷新缓存。

答案 1 :(得分:1)

访问volatile变量应该绕过缓存,而不是刷新它。因此清除缓存不应影响volatile的行为。 这个bug如何表现出来?您是否在Thread.sleep()之后和同一个线程上看到过时的值? 很多年前,我为Java兼容性测试套件编写了测试。其中一个测试证明,volatile变量可以从缓存中读取,而不是从主内存中读取。我想知道这个bug是否仍然存在。请将详细信息发送至rfq(at)list.ru,我将尝试创建令人信服的测试。

答案 2 :(得分:1)

我不确定这是否是这种情况(需要更多详细信息!),但有一件事需要注意,如果你看到一个关于volatile的硬线程错误,那就是volatile不一定是原子的。

即。你可能认为你已经更新了一个volatile变量并且新值应该是可见的,但事实上你并没有因为完整的更新没有完成。

http://www.ibm.com/developerworks/java/library/j-jtp11234/

答案 3 :(得分:1)

您是否尝试使用AtomicInteger

如果值始终由同一个线程更改/读取,我无法看到如何从cpu缓存中获取错误版本的volatile int。也许尝试打印出变量上每次读/写时哪个线程处于活动状态,只是为了100%确定:

System.out.println(Thread.currentThread().getName());