Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,如何刷新CPU内存缓存,使其从RAM内存中检索最新的数据?_Java_Concurrency_Volatile_Synchronized - Fatal编程技术网

在Java中,如何刷新CPU内存缓存,使其从RAM内存中检索最新的数据?

在Java中,如何刷新CPU内存缓存,使其从RAM内存中检索最新的数据?,java,concurrency,volatile,synchronized,Java,Concurrency,Volatile,Synchronized,计算机有RAM内存,但也有更小更快的CPU内存缓存。 Java内存模型保证在使用volatile访问变量时刷新CPU内存缓存,但由于我们只在单个线程的单个类中使用该volatile变量,因此JIT不一定会对其进行优化 要诊断一个bug(只有在调用Thread.sleep()足够长的时间后才会表现出来),我们需要能够这样做(而不是sleep()): 实现这种方法最简单、最可靠的方法是什么?它应该保证不会JIT优化缓存刷新。 我们只能在启用JIT的情况下复制错误,因此禁用JIT不是一个选项。通常不能

计算机有RAM内存,但也有更小更快的CPU内存缓存。 Java内存模型保证在使用
volatile
访问变量时刷新CPU内存缓存,但由于我们只在单个线程的单个类中使用该volatile变量,因此JIT不一定会对其进行优化

要诊断一个bug(只有在调用Thread.sleep()足够长的时间后才会表现出来),我们需要能够这样做(而不是sleep()):

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

通常不能。除了性能,缓存的存在对应用程序是透明的。这也适用于多处理器系统,只要缓存系统是“缓存一致的”,这实际上是目前使用的所有平台

因此,您的bug位于其他位置


像易失性块和同步块这样的事情本身并不影响缓存的一致性,而是寄存器优化、原子指令的使用(例如,包括刷新存储缓冲区,这与缓存不同!),等等。这些是您应该关注的内容(鉴于您的描述中缺乏细节,很难说,但作为第一个猜测…),而不是尝试刷新缓存

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

我不确定这里是否存在这种情况(需要更多详细信息!),但如果您在volatile周围看到硬线程错误,需要注意的一点是volatile不一定是原子的

i、 你可能认为你已经更新了一个可变变量,新的值应该是可见的,但事实上你没有,因为完整的更新还没有完成

你有没有试过使用一个

如果值总是由同一线程更改/读取,我看不出如何从cpu缓存中获取错误版本的volatile int。可能尝试打印出变量每次读/写时哪个线程处于活动状态,以便100%确定:

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

进入和退出
同步的
块也应该工作。我从来没有听说过JIT优化易失性写操作。你有任何文件证明它会这样做吗?@Johannes根本没有证据,只是怀疑:)你说的是一个bug。它的症状是什么?当您只使用一个线程时,易失性、JIT和并发性问题很奇怪。如果可能的话,请发布一个带有“睡眠”的可测试代码来产生bug。你可能看错了方向。你在赏金评论中的“刷新存储缓冲区”是什么意思?你选择了相关的词了吗?请提供详细信息和代码在这种情况下,如何可靠地刷新存储缓冲区?@GeoffreyDeSmet:视情况而定。在x86上,例如“mfence”指令。在Java中,使用volatile、同步块等应该会导致JVM在必要时发出此类指令。
System.out.println(Thread.currentThread().getName());