2012-05-14 16 views
10

私はWeakHashMapのソースコードを見て取り、これに出くわした:ReferenceQueueで同期する必要がありますか?

private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); 

private void expungeStaleEntries() { 
    for (Object x; (x = queue.poll()) != null;) { 
     synchronized (queue) { 
      /* snip */ 
     } 
    } 
} 

この方法はReferenceQueueに同期しないのはなぜ? WeakHashMap自体は、スレッドセーフではありません:

ほとんどのコレクションクラスと同様、このクラスは同期されていません。 WeakHashMapを同期させるには、 Collections.synchronizedMapメソッドを使用します。この実装の詳細は、(GCがThread独自のからそれを修正することになるので)、何とか、ReferenceQueue自体のスレッドの安全性を確保することであると信じている私を導い

。しかし、the documentation for ReferenceQueueには同時性に関する懸念事項は何も言及されておらず、ReferenceQueueのソースコードを見ても、それ自体は同期していない(内部ロックを使用している)ことさえある。

なぜWeakHashMapReferenceQueueで同期していますか?私はそれを使用するたびにReferenceQueueで同期する必要がありますか?

答えて

6

ReferenceQueueを見ると、remove()メソッドが新しいエントリが利用可能になるまでブロックされると記載されているため、プラットフォーム内のスレッドを明示的にサポートしていることがわかります。

WeakHashMapに表示されている​​は、ReferenceQueueにアクセスする複数のスレッドが適切に同期されていることを保証しています。

これは興味がありますか?bug at bugs.sun.comが面白いかもしれません。

あなたの質問に答えるために、私はReferenceQueueの外部同期は、それが単一のスレッドによってのみアクセスされることを確認する必要はないと思います。私は複数のスレッドから単一のReferenceQueueをコンシューマとして使用することはできません(そして、良い理由は考えられません)。

+0

+1ニースfind - 読み込み方法が地図をどのように変更するか興味深い。 –

+1

@andersojああ、そのバグレポートはそれを明確にしています。 'WeakHashMap'で' size'を呼び出すと根底にあるマップが変更される可能性があるので、 'size'を同時に呼び出すユーザーは誤ってそれを壊す可能性があります。この動作は、複数のスレッドが問題なくコンテンツを読むことを可能にするほとんどの(すべての)JDKの 'Map'実装に反しているので、クラスをスレッドセーフなものにして' Map'仕様である。 – Jeffrey

+0

@John VintたとえばLinkedHashMap getはacessの注文を格納するためマップを変更します – gstackoverflow

関連する問題