计算机具有RAM内存,但它也具有小巧,快速的CPU内存缓存。
Java内存模型保证在访问具有volatile
的变量时刷新CPU内存缓存,但由于我们仅在单个线程中的单个类中使用该volatile变量,因此不确定JIT是否只是优化它。
要诊断一个错误(当我们在特定点调用Thread.sleep()足够长时才会出现这个错误),我们需要能够做这样的事情(而不是sleep()):
System.clearCpuCache();
实现这种方法的最简单,最可靠的方法是什么?它应该保证它不会JIT优化缓存刷新。 我们只能在启用JIT的情况下重现我们的错误,因此禁用JIT不是一种选择。
答案 0 :(得分:8)
因此,你的错误在其他地方。
易失性和同步块之类的东西本身不会影响缓存一致性,而是寄存器优化,使用原子指令(包括刷新存储缓冲区,这与缓存不同!),以及等等。这些是你应该看的东西(好吧,鉴于你的描述中缺乏细节,很难说,但作为第一个猜测..),而不是试图刷新缓存。
答案 1 :(得分:1)
访问volatile变量应该绕过缓存,而不是刷新它。因此清除缓存不应影响volatile的行为。 这个bug如何表现出来?您是否在Thread.sleep()之后和同一个线程上看到过时的值? 很多年前,我为Java兼容性测试套件编写了测试。其中一个测试证明,volatile变量可以从缓存中读取,而不是从主内存中读取。我想知道这个bug是否仍然存在。请将详细信息发送至rfq(at)list.ru,我将尝试创建令人信服的测试。
答案 2 :(得分:1)
我不确定这是否是这种情况(需要更多详细信息!),但有一件事需要注意,如果你看到一个关于volatile的硬线程错误,那就是volatile不一定是原子的。
即。你可能认为你已经更新了一个volatile变量并且新值应该是可见的,但事实上你并没有因为完整的更新没有完成。
答案 3 :(得分:1)
您是否尝试使用AtomicInteger?
如果值始终由同一个线程更改/读取,我无法看到如何从cpu缓存中获取错误版本的volatile int。也许尝试打印出变量上每次读/写时哪个线程处于活动状态,只是为了100%确定:
System.out.println(Thread.currentThread().getName());