如果我使用 32 位原语并且我的函数是幂等的,为什么我可以跳过 DCL 的任何同步?

Why could I skip any synchronization for DCL if I use 32-bit primitives and my function idempotent?

我看过以下经典名篇: The "Double-Checked Locking is Broken" Declaration

我有一个问题:

In fact, assuming that the computeHashCode function always returned the same result and had no side effects (i.e., idempotent), you could even get rid of all of the synchronization.

// Lazy initialization 32-bit primitives
// Thread-safe if computeHashCode is idempotent
class Foo { 
  private int cachedHashCode = 0;
  public int hashCode() {
    int h = cachedHashCode;
    if (h == 0) {
      h = computeHashCode();
      cachedHashCode = h;
      }
    return h;
    }
  // other functions and members...
  }

这篇文章是为 java 4 写的。它对 java 8+ 是否仍然有效?

computeHashCode()真的只会被调用一次吗?

不,不能保证只调用一次,但这无关紧要。

如果computeHashCode是幂等的,多次调用它没有效果,因此线程不会相互干扰。

不可以,可以执行多次。同步 "flushes" 对其他线程的更改,如果没有它,一个线程中所做的更改理论上永远不会在该线程之外进行通信。

但是,这篇文章并没有说 computeHashCode 将被恰好调用一次,只是竞争条件不会导致任何问题。 int 写入保证是原子的,并且如果 computeHashCode 是幂等的(这要求 class 及其字段有效地最终),您只需用相同的值覆盖以前的值, 所以没有什么不好的事情发生。

来自您发布的同一篇文章:

JDK5 and later extends the semantics for volatile so that the system will not allow a write of a volatile to be reordered with respect to any previous read or write, and a read of a volatile cannot be reordered with respect to any following read or write.

With this change, the Double-Checked Locking idiom can be made to work by declaring the helper field to be volatile. This does not work under JDK4 and earlier.

这意味着双重检查锁定从Java 5.

开始是安全的

Is it true that computeHashCode() will be invoked only once?

没有。该方法不以任何方式同步。但是,它是线程安全的,因为它是幂等的。