2017-03-13 11 views
1

私はJava Concurrency in Practiceを経由しています。いくつかは私に次のようになり、リスト2.8のコードで私が午前、次の疑問を説明することができます: -読み取りを変数に同期させる必要がありますか?

@ThreadSafe 
public class CachedFactorizer implements Servlet { 
    @GuardedBy("this") private BigInteger lastNumber; 
    @GuardedBy("this") private BigInteger[] lastFactors; 
    @GuardedBy("this") private long hits; 
    @GuardedBy("this") private long cacheHits; 
    public synchronized long getHits() { return hits; } 
    public synchronized double getCacheHitRatio() { 
     return (double) cacheHits/(double) hits; 
    } 
    public void service(ServletRequest req, ServletResponse resp) { 
     BigInteger i = extractFromRequest(req); 
     BigInteger[] factors = null; 
     synchronized (this) { 
      ++hits; 
      if (i.equals(lastNumber)) { 
       ++cacheHits; 
       factors = lastFactors.clone(); 
      } 
     } 
     if (factors == null) { 
      factors = factor(i); 
      synchronized (this) { 
       lastNumber = i; 
       lastFactors = factors.clone(); 
      } 
} 
     encodeIntoResponse(resp, factors); 
    } 
} 
  1. cacheHitsへのアップデートとhitsと同期する必要getCacheHitRatio方法は同期ブロックからのものですgetCacheHitRatioは値を読み取っているだけですか?
  2. なぜclonelastFactorsfactorsで使用されましたか? factors=lastFactorsは使えませんか?これはこの章では説明していません。
+0

変数をvolatileにすることを検討してください。 –

答えて

1

1)書き込み側で​​のみ

1.1コードブロックに入る、​​前に以前のすべての操作が行われ、メインメモリに書き込まれることを保証します。

1.2ブロック内で操作されるすべての変数は、メインメモリから直接の値を持ちます(つまり、すべてのキャッシュラインがリフレッシュされます)。

1.3ブロックの最後に、変更された変数がブロックを終了する前にメインメモリに書き込まれます。

他のスレッドから読み取るときは、スレッドキャッシュ値(CPUキャッシュラインが使用前に正常にリフレッシュされている)からではなく、メインメモリから最新の値を読み取る必要があります。

2)私は何が要因か分かりませんが、私はそれが共有オブジェクトだと思います。そうであれば、Javaの代入演算子は単にポインタ代入です。つまり、同じファクタオブジェクトを指しています。したがって、その上で動作する(読み取りおよび書き込み)には依然として同期が必要です。

+0

Regd#2 'factor'は単に' service() 'の中で宣言されたローカル変数です。では、ここで 'clone()'を使う必要がありますか? – tuk

+0

コードを読んで、私はそれがオブジェクトだと思います(プリミティブは、とにかく 'clone()'を持っていません)。だからええ、あなたはまだ完全に内容をコピーしない限り、このオブジェクトの爽やかな問題に遭遇します。まさにここで 'clone()'がしていることです。 –

+0

'getCacheHitRatio()'が 'synchronized'する必要があるもっと重要な理由があります:それは原子的ではありません!それが同期されていない場合、 'hits'値と' cachehits'から ''一緒に行く ''の比率を計算することは可能です。つまり、実際の比率ではない値を返すことができます。これは、このアプリケーションでは重要ではないように思われるかもしれませんが、他のアプリケーションでは同じミスが悲惨です。 –

関連する問題