Java 易失性在x86处理器上没有用处

Java 易失性在x86处理器上没有用处,java,concurrency,synchronization,volatile,Java,Concurrency,Synchronization,Volatile,我在某个地方读到,x86处理器具有缓存一致性,可以在每次写入时跨多个内核同步字段的值 这是否意味着,如果我们计划只在x86处理器上运行,我们就可以不用java中的“volatile”键盘来编写代码 更新: 好的,假设我们不考虑指令重新排序的问题,我们是否可以假设x86处理器上不存在分配给非易失性字段的问题,该字段在内核中不可见?否--volatile关键字的含义不仅仅是缓存一致性;它还限制了运行时可以做什么和不能做什么,比如延迟构造函数调用。可以同步字段的值和总是同步字段的值之间有很大的区别。如

我在某个地方读到,x86处理器具有缓存一致性,可以在每次写入时跨多个内核同步字段的值

这是否意味着,如果我们计划只在x86处理器上运行,我们就可以不用java中的“volatile”键盘来编写代码

更新:


好的,假设我们不考虑指令重新排序的问题,我们是否可以假设x86处理器上不存在分配给非易失性字段的问题,该字段在内核中不可见?

否--
volatile
关键字的含义不仅仅是缓存一致性;它还限制了运行时可以做什么和不能做什么,比如延迟构造函数调用。

可以同步字段的值和总是同步字段的值之间有很大的区别。如果您有volatile,x86可以同步字段,否则它不会也不应该同步

注意:易失性访问可能比非易失性访问慢10-30倍,这是非易失性访问不能一直进行的一个关键原因


顺便说一句:你知道有任何多核的普通x86处理器吗。我原以为大多数是支持x86的x64。

我可以保证
volatile
有一些用处。我遇到过这样的情况:一个线程的变量为“null”,另一个线程的变量值为该线程中设置的正确值。调试并不有趣。对所有共享字段使用volatile:)

关于JVM在
volatile
中的行为,有非常精确的规范,如果它选择使用特定于cpu的指令来实现这一点,则对您有好处

您应该说“我们知道在这个平台上cpu的行为类似于…”的唯一地方是在本机代码中链接时,它需要与cpu一致。在所有其他情况下,按照规范编写


请注意,volatile关键字对于编写在多个cpu上运行的健壮代码非常重要,每个cpu都有自己的缓存,因为它告诉JVM忽略本地缓存,获取官方值,而不是5分钟前的缓存值。您通常都希望这样。

关于您的更新:不,我们不能。其他线程可以在不更新变量的情况下读取过时的值。还有另一个问题:JVM可以优化代码,只要它能够保证单线程行为是正确的

这意味着:

public boolean var = true;
private void test() {
    while (var) {
       // do something without changing var
    }
}

如果愿意,可以通过JIT优化为while(true)

写入字节码甚至不必导致写入机器码。除非是易失性写入。

Java支持DMA(如CD驱动器和内存映射I/O)吗?为什么?不管怎样,只要使用它。如果你有多个处理器怎么办?特别是,当Hotspot将代码编译成本机代码时,如何允许它优化你的代码。你有任何关于10-30倍慢度的基准/示例吗?我在变量上使用了volatile,这些变量的读取次数非常非常多,volatile版本和非volatile版本之间几乎没有性能差异。如果只在单个线程中访问字段,则性能差异很小。但是,当一个字段在线程之间共享时,它要大得多。即缓存相当智能。你是否积极地在线程之间共享该字段?我发现易失性访问需要26 ns,而非易失性访问需要2 ns。问题是要避免微基准测试的陷阱,因为微基准测试可以将所有的东西都简化为几乎没有的东西当你说访问是指存储/加载还是两者兼而有之。缓存相关系统上的易失性负载与正常负载非常接近。@John V,我发现这在很大程度上取决于系统的体系结构。用于访问过时值的加载和用于访问未过时值的加载往往非常不同。