在 java 中同步确保其他线程的内存更新?

Synchronized in java ensuring memory updates for other threads?

由于很多误解,我从头开始重新表述了这个问题。问题的意图没有改变。许多评论仍然引用旧问题文本。

关于 volatile 的文档声明它确保其他线程以一致的方式看到内存更新。但是,volatile很少使用。

据我所知,synchronized 块的目的是使线程不会同时执行这些临界区。 synchronized 是否也会像 volatile 一样导致对其他线程的一致内存更新?

当然,使用临界区是可行的。使用不稳定的作品。但是您必须使用一些东西来确保您获得所需的内存可见性。否则,您的代码只能靠运气或意外运行——如果它运行的话。

is it simply true that all memory is consistently updated between threads in Java when happening inside a locked section?

简答:
是的

长答案:

在 JVM 中,引用类型和除 doublelong 之外的所有原始类型的赋值是 "atomic"。 IE。任何线程要么看到一个值,要么看到另一个值,但永远不会看到一半更新的值。所以你甚至可以说内存 "consistently" 更新而不做任何事情(这有一些微妙之处所以不要尝试实际使用这个特性!它被用于实现 String#hashCode)。

但是,如果没有 volatile,更改可能不会像您所说的那样立即可见("immediately" 有点误导。有关详细信息,请参阅 this answer)。 synchronized 关键字确实以与 volatile 相同的方式使更改立即可见。那你问volatile有什么意义呢。

基本上,您可以使用 synchronizedvolatile 可以做的任何事情。所以 volatile 并没有给你新的可以做的事情。但是,它仍然有用,因为它避免了锁定。 volatile 的性能通常更好(权衡是功能较少;synchronized 可以做 volatile 可以做的所有事情,但反之亦然)并且也没有死锁危险。在我看来,如果可以使用 volatile,则应该使用 volatile。但是有很多人不同意,认为你应该到处使用 synchronized

Java其实没有"volatile memory"的概念。相反,volatile 关键字改变了 JVM 对字段何时以及如何写入和读取的保证。维基百科对 Java(和其他语言)的 volatile.

的含义进行了很好的细分

非常粗略地说,一个volatile字段相当于一个总是被读取和写入的字段,如下所示:

// read
T local;
synchronized {
  local = field;
}

// ... do something with local

// write
synchronized {
  field = local;
}

换句话说,volatile字段的读写是原子的,对其他线程总是可见的。对于简单的并发操作,这就足够了,但您可能仍需要显式同步以确保正确处理复合操作。 volatile 的优点是它更小(只影响一个字段),因此可以比同步代码块更有效地处理。

你会从我的伪翻译中注意到,对该字段的任何修改或突变都不是 synchronized,这意味着没有记忆障碍或发生之前的关系强加给你可能用检索到的对象。 only volatile 提供的是线程安全的字段读写。这是一项功能,因为当您只需要更新字段时,它比 synchronized 块更有效。

如果您以前没有阅读过 Java Concurrency in Practice,我强烈建议您阅读;它很好地概述了您需要了解的有关 Java 中并发性的所有信息,包括 volatilesynchronized.

之间的区别

Obviously, this doesn't happen, or else I would have encountered such a problem during my career. I never did.

请注意,这是一种错误的推理方式。您完全有可能做错事但从未受其影响或根本没有注意到其影响。例如,过度同步的代码(如 Vector)将正常工作,但 运行 比其他解决方案慢得多。