应该同步对地图对象的java synchronizedMap操作

时间:2013-01-28 11:41:44

标签: java concurrency synchronization

我的代码使用以下内容:

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 Doc了解到,一旦迭代我的m_MsgHash我必须使用synchronized关键字。但我的问题是,在我的地图中使用提取的synchronized时,是否需要使用Object

3 个答案:

答案 0 :(得分:2)

对于synchronizedMap结果的简单操作,例如get,您不需要“synchronized”。如果obj引用的对象本身是从多个线程访问的,并且至少被其中一个线程修改过,则需要在同一个对象上同步对它的所有访问,否则确保多线程正确。

答案 1 :(得分:2)

不,不要:m_MsgHash.get(Id);已同步,因此它是一个线程安全的操作。一旦你引用了obj,你可以随心所欲地做任何事情,而不需要同步,因为它独立于地图生活(只要你不在线程之间共享它,但这里是一个局部变量)。

但请注意,您的地图未按原样安全发布。如果一个线程调用init而另一个调用HandleMsg,则第二个线程可能会看到该地图的空值。

安全发布地图的一种简单方法是使其成为最终版并在ClassA的构造函数中实例化它。

答案 2 :(得分:0)

不需要。无论何时调用Collections.synchronizedMap它都会创建一个实现Map接口的类,并具有所有方法synchronized。这称为Java Monitor Pattern,其中底层LinkedHashMap受Java Monitor保护以启用线程安全性。您需要在循环时进行同步,因为Map可能会在循环时发生变化。

putgetremove等操作受类Monitor保护,因此不需要在同步方法中,除非它们是复合操作的一部分,例如Check - 然后,法案。