我的代码使用以下内容:
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
?
答案 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可能会在循环时发生变化。
但put
,get
和remove
等操作受类Monitor保护,因此不需要在同步方法中,除非它们是复合操作的一部分,例如Check - 然后,法案。