2015-09-11 31 views
0
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; 
} 

我不明白的地方第二次检查的条件是“毫微== expirationNanos”,而不是“毫微秒== 0 ||现在 - 毫微> = 0”。如果两个名为threadA和threadB的线程同时调用get方法并进入同步代码,threadA将获得该锁。当threadA执行所有代码并释放锁定时,param expirationNanos的值也等于nanos的值。 ThreadB不能直接返回t实例,它也会执行代码。如果条件是“nano == 0 || now-nanos> = 0”,情况就不会发生。ExpiringMemoizingSupplier的方法实施名为Get

回答

0

如果第二次检查中的条件是nanos == 0 || now - nanos >= 0,它总会是真的,因为这些是局部变量。还要注意,当expirationNanos设置为nanos时,nanos先前被设置为now + durationNanos。换句话说,当线程B进入同步块时,nanos == expirationNanos应该而不是为真。

+0

虽然'nanos'设置为'now + durationNanos',expirationNanos也设置为'(nanos == 0)? 1:nanos'。换句话说,当线程B进入同步块时,'nanos == expirationNanos'应该为真。如果'nanos == now + durationNanos; expirationNanos ==(nanos == 0)? 1:nanos'被修改了'expirationNanos == now + durationNanos;',那会好起来的。 –

+0

我认为你可能误解了一些东西。请记住'nanos'是一个局部变量;线程B具有与线程A不同的值。当线程B进入时,'nanos == expirationNanos'应该为false。 – ColinD

+0

我明白了,非常感谢你~~^_ ^ –