HashMapの中の個々のメソッドを同期対Collection.synchronizedMap
-
19-09-2019 - |
質問
Collections.synchronizedMap()と同期したすべてのメソッドとHashMapのラッパーの違いは何ですか。私は内部的にすべてのメソッドに同じロックを維持)Collections.synchronizedMap(becuase任意の違いを参照してくださいいけない。
基本的に、次のコードスニペットの違いは何である
Class C {
Object o;
public void foo() {
synchronized(o) {
// thread safe code here
}
}
}
と
Class C {
Object o;
public synchronized void foo() {
}
}
解決
一つだけ違いがあります:
Collections.synchronizedMap ののそのものよりも、別のモニターを使用することができます。
同期の方法を用いては意味し、ラッパーがモニターされ、そして包装の外側からロックすることができ、sychnchonized(this)
ブロックを使用するのと同じである。
、あなたはそれを非表示にする必要があります。
あなたがスレッドセーフな方法で複数のメソッドを呼び出したい場合は、他の側では、それはコレクション全体をロックする最も簡単な方法である(しかし、それは確かに、非常にスケーラブルではありません)。
Psは:あなたがあなたのラッパーを変更せずに、後から別のマップの実装に切り替えることができるので、再利用のために、それは、メソッドがクラスをオーバーライドするよりもバックアップ地図への呼び出しを委任する方が良いでしょう。
他のヒント
両方のアプローチは、オブジェクト上のモニターを取得するので、正確に同じ実行する必要があります。違いの主な理由は、建築です。同期ラッパーは簡単に基本的な非スレッドセーフなバリエーションを拡張することができます。
のConcurrentHashMapを使用し、いずれかを使用しないと述べました。それは(彼らはオーバーヘッド+競合の面で同じよう)のいずれかよりも、アプローチを使用してはるかに高速ですので、それはロックストライピングを使用しています。ロックストライピングは補助配列のセグメントが独立にロックされることを可能にします。これは、2つのスレッドが同じロックを取得するよう要求することが劣勢であることを意味します。
車輪の再発明し、APIで提供されているものは使用しないでください。
あなたは、常に一つの大きな特色のクラスにすべてのものとすべてのfearturesをひとまとめではなく、飾る必要があります。
常にプレーン地図を取り、コレクションでそれを飾るか、java.util.concurrentのを使用し、もう1つはアトミックに検査し、マップを更新することができますので、本物のロックを使用します。明日はあなたがツリーマップにハッシュテーブルを変更する場合がありますし、あなたのハッシュテーブルで立ち往生している場合、あなたはトラブルになります。
では、なぜあなたは聞いていますか? :)あなたが本当にクラスはjava.utilパッケージに配置されている場合、一部の魔法が起こると、そのJavaコードは、いくつかのトリッキーな方法で動作することを信じますか?
これは本当にただ同期{}ブロックとより多くの何もすべてのメソッドをラップします。
UPD:違いは、あなたがあなたの代わりに自分ですべての同期のものをやっての同期コレクションを使用する場合は、ミスを犯すためにはるかに少ないチャンスを持っているということです。
。 UPD 2:あなたがソースに見ることができるように、彼らはモニターとして「mutex'・オブジェクトを使用します。あなたは、メソッドのシグネチャ(すなわちsynchronized void doSmth()
)あなたのオブジェクトの現在のインスタンス(すなわちthis
)で同期修飾子を使用すると、モニターとして使用されています。以下のコードの二つのブロックは同じです。
1。
synchronized public void doSmth () {
someLogic ();
moreLogic ();
}
synchronized public static void doSmthStatic () {
someStaticLogic ();
moreStaticLogic ();
}
2。
public void doSmth () {
synchronized (this) {
someLogic ();
moreLogic ();
}
}
public static void doSmthStatic () {
synchronized (ClassName.class) {
someStaticLogic ();
moreStaticLogic ();
}
}
スレッドセーフな場合は、同時実行パッケージデータ構造を使用します。ラッパークラスを使用すると、シーケンシャルキューに地図へのすべてのアクセスを削減します。
a)の地図では全く異なるポイントで操作を行うために待機しているスレッドが同じロックを待っていることでしょう。スレッドの数に基づいて、これは、アプリケーションのパフォーマンスに影響を与える可能性があります。
b)は地図上の化合物の操作を考えてみましょう。シングルロックでラッパーを使用することは助けにはなりません。例えば。操作の種類を「存在する場合、その後追加見て」。スレッドのsyncronizationが再び問題になります。