ExpiringMemoizingSupplier的方法名为get的实现

时间:2015-09-11 10:50:49

标签: java guava

public T get() {
  // Another variant of Double Checked Locking.
  //
  // We use two volatile reads.  We could reduce this to one by
  // putting our fields into a holder class, but (at least on x86)
  // the extra memory consumption and indirection are more
  // expensive than the extra volatile reads.
  long nanos = expirationNanos;
  long now = Platform.systemNanoTime();
  if (nanos == 0 || now - nanos >= 0) {
    synchronized (this) {
      if (nanos == expirationNanos) { // recheck for lost race
        T t = delegate.get();
        value = t;
        nanos = now + durationNanos;
        // In the very unlikely event that nanos is 0, set it to 1;
        // no one will notice 1 ns of tardiness.
        expirationNanos = (nanos == 0) ? 1 : nanos;
        return t;
      }
    }
  }
  return value;
}

我不明白第二次检查的条件是“nanos == expirationNanos”,而不是“nanos == 0 || now - nanos> = 0”。如果名为threadA和threadB的两个线程调用get方法并同时转到同步代码,则threadA获取锁。当threadA执行所有代码并释放锁时,param expirationNanos'的值也等于nanos'的值。 ThreadB不能直接返回t实例,它也执行代码。如果条件为“nano == 0 || now-nanos> = 0”,则情况不会发生。

1 个答案:

答案 0 :(得分:0)

如果第二次检查中的条件是nanos == 0 || now - nanos >= 0,那么它总是正确的,因为它们是局部变量。另请注意,当expirationNanos设置为nanos时,nanos之前已设置为now + durationNanos。换句话说,当线程B进入同步块时,nanos == expirationNanos应该为真。