Java jvm是否保证在切换线程后更新处理器缓存?

Java jvm是否保证在切换线程后更新处理器缓存?,java,multithreading,Java,Multithreading,面试官问我,如果我们确信线程永远不会干扰,那么不使用volatile有什么危险吗 我们有: int i = 10; // Thread 1 i++; // await some time and switch to Thread 2 getI(); 我不使用任何同步。 通过第二个线程接收过期的i值是否有任何危险 如果没有volatile或synchronized或读/写屏障,则无法保证其他线程会看到您所做的更改,无论您等待多长时间。特别是boolean字段可以内联到代码中,并且实际上不执

面试官问我,如果我们确信线程永远不会干扰,那么不使用
volatile
有什么危险吗

我们有:

int i = 10; 
// Thread 1 
i++; 
// await some time and switch to Thread 2
getI();
我不使用任何同步。

通过第二个线程接收过期的
i
值是否有任何危险

如果没有
volatile
synchronized
或读/写屏障,则无法保证其他线程会看到您所做的更改,无论您等待多长时间。特别是
boolean
字段可以内联到代码中,并且实际上不执行读取。理论上,如果JVM检测到该字段没有被线程更改,则可以内联
int
值(但我不相信它确实会这样做)

我们确信线程永远不会干扰


这不是您可以知道的,除非在执行更新时读取线程没有运行。当线程启动时,它将看到在它启动之前发生的任何更改。

如果没有
volatile
synchronized
或读/写屏障,则无法保证其他线程会看到您所做的更改,无论您等待多长时间。特别是
boolean
字段可以内联到代码中,并且实际上不执行读取。理论上,如果JVM检测到该字段没有被线程更改,则可以内联
int
值(但我不相信它确实会这样做)

我们确信线程永远不会干扰


这不是您可以知道的,除非在执行更新时读取线程没有运行。当线程启动时,它将看到在启动之前发生的任何更改。

您可能会收到过时的值,是的

简而言之,原因是:

Java中的每个线程都有自己的小“缓存”。出于性能原因,线程在自己的内存中保留“主”数据的副本。所以你基本上有一个主内存和一个本地内存。volatile关键字强制线程访问主内存,而不是其本地内存


有关更多信息,请参阅此链接:

您可能会收到过时的值,是的

简而言之,原因是:

Java中的每个线程都有自己的小“缓存”。出于性能原因,线程在自己的内存中保留“主”数据的副本。所以你基本上有一个主内存和一个本地内存。volatile关键字强制线程访问主内存,而不是其本地内存


有关更多信息,请参阅此文档:

如果面试官问我这个问题,我会用Java语言规范来回答。JLS中没有“缓存”或“主内存”。JLS讨论了字段(也称为实例变量和类变量),并对线程a中发生的字段更新何时在线程B中可见做出了非常具体的保证。实现细节,如“缓存”和“内存屏障”,可能因平台而异,但是对于JLS来说正确的程序(理论上)应该在任何Java平台上都是正确的。

如果面试官问我这个问题,我会用Java语言规范来回答。JLS中没有“缓存”或“主内存”。JLS讨论了字段(也称为实例变量和类变量),并对线程a中发生的字段更新何时在线程B中可见做出了非常具体的保证。实现细节,如“缓存”和“内存屏障”,可能因平台而异,但是对于JLS来说正确的程序(理论上)在任何Java平台上都应该是正确的。

注意:访问volatile很少意味着会影响主内存,因为这会影响性能。但是,它可以确保您看到一致的值。事实上,这是通过内核中的二级缓存在硬件中实现的,二级缓存通过一条特殊的总线直接相互通信。i、 它甚至可能不会命中三级缓存。注意:访问volatile很少意味着您会命中主内存,因为这会影响性能。但是,它可以确保您看到一致的值。事实上,这是通过内核中的二级缓存在硬件中实现的,二级缓存通过一条特殊的总线直接相互通信。i、 e.它甚至可能不会命中L3缓存。这个问题对于理解易失性概念很有用:这个问题对于理解易失性概念很有用: