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

4

3 回答 3

2

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

于 2013-01-28T11:45:00.883 回答
2

不,你不需要:m_MsgHash.get(Id);是同步的,所以它是一个线程安全的操作。一旦你有了对它的引用,obj你就可以用它做任何你想做的事情,而无需同步,因为它独立于地图存在(只要你不跨线程共享它,但这里它是一个局部变量)。

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

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

于 2013-01-28T11:45:42.257 回答
0

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

但是像put,get和之类的动作remove受类 Monitor 保护,因此不需要在同步方法中,除非它们是复合动作的一部分,例如 Check-Then-Act。

于 2013-01-28T11:52:18.353 回答