0

私のコードは以下を使用しています:

public class Obj{
   public String someOperation(){...}
};

public class ClassA{
   private Map<Integer, Object> m_MsgHash;

   public boolean init()
   {
      m_MsgHash = Collections.synchronizedMap(new LinkedHashMap<Integer, Object>(1001, 1.0F, true));
   }
   private Object fetchFromHash(int Id)
   {
     return m_MsgHash.get(Id);
   }

   public void HandleMsg(int Id)
   {
     Object obj = fetchFromHash(Id);
    // do some operation on obj needs to be synchronized ?
    //synchronized (m_MsgHash) {
    obj.someOperation();
    //}
   }
}

Java Docm_MsgHashから、 my i を反復するにはsynchronizedキーワードを使用する必要があることを理解しています。しかし、私の質問は、マップからsynchronizedフェッチしたものを使用するときに使用する必要がありますか?Object

4

3 に答える 3

2

取得など、synchronizedMap の結果に対する単純な操作の場合、「同期」は必要ありません。obj によって参照されるオブジェクト自体が複数のスレッドからアクセスされ、それらの少なくとも 1 つによって変更される場合、そのオブジェクトへのすべてのアクセスを同じオブジェクトで同期させるか、そうでなければマルチスレッドの正確性を確保する必要があります。

于 2013-01-28T11:45:00.883 に答える
2

いいえ、しないでください:m_MsgHash.get(Id);同期されているため、スレッドセーフな操作です。そして、参照をobj取得すると、マップとは独立して存在するため、同期する必要なく、必要なことを何でも実行できます (スレッド間で共有しない限り、ここではローカル変数です)。

ただし、マップはそのままでは安全に公開されないことに注意してください。スレッドが を呼び出しinit、別のスレッドが を呼び出した場合HandleMsg、2 番目のスレッドがマップの null 値を参照する可能性があります。

マップを安全に公開する簡単な方法は、マップを最終的なものにし、ClassA のコンストラクター内でインスタンス化することです。

于 2013-01-28T11:45:42.257 に答える
0

必要ありません。呼び出すたびに、インターフェイスCollections.synchronizedMapを実装し、すべてのメソッドを持つクラスが作成されます。これは と呼ばれ、基になる LinkedHashMap が Java モニターによって保護され、スレッド セーフが有効になります。ループ中にマップが変更される可能性があるため、ループ中に同期する必要があります。MapsynchronizedJava Monitor Pattern

ただしputgetやなどのアクションremoveはクラス Monitor によって保護されているため、Check-Then-Act などの複合アクションの一部でない限り、同期メソッド内にある必要はありません。

于 2013-01-28T11:52:18.353 に答える