[英]Synchronized collection vs synchronized method?
我有一个包含一个将由多个线程使用的集合的类容器:
public class Container{
private Map<String, String> map;
//ctor, other methods reading the map
public void doSomeWithMap(String key, String value){
//do some threads safe action
map.put(key, value);
//do something else, also thread safe
}
}
最好声明synchronized
方法:
public synchronized void doSomeWithMap(String key, String value)
还是使用标准的线程安全装饰器?
Collections.synchronizedMap(map);
一般而言,同步地图将保护大多数对其的访问,而无需进一步考虑。 但是,“同步映射”对于迭代而言并不安全,这可能是一个问题,具体取决于您的用例。 当迭代其任何集合视图时,用户必须手动在返回的地图上进行同步。
如果可以满足您的用例,请考虑使用ConcurrentHashMap 。
如果该对象还有其他状态需要防止并发错误,那么您将需要使用sync或Lock
。
如果看一下SynchronizedMap
的实现,您会看到它只是一个包装了非线程安全映射的映射,该映射在调用任何方法之前使用互斥体
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
public Set<Map.Entry<K,V>> entrySet() {
synchronized (mutex) {
if (entrySet==null)
entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
return entrySet;
}
}
如果您想要保护的是get
和put
,那么此实现将为您完成它。
但是,如果您希望Map可以被两个或更多线程迭代并更新,则不适合使用这种情况,在这种情况下,您应该使用ConcurrentHashMap
。
如果您在doSomeWithMap
内部doSomeWithMap
的其他操作如果由不同的线程并发完成(例如,它们更新类级变量)会导致问题,那么您应该同步整个方法。 如果不是这种情况,则应使用同步Map
,以最小化将同步锁保留在原处的时间。
如果您doSomeWithMap
方法将访问地图不止一次 ,你必须同步doSomeWithMap
方法。 如果唯一的访问是显示的put()
调用,那么最好使用ConcurrentHashMap 。
请注意,“多次调用”是任何调用,而迭代器本质上就是许多“获取”操作。
您可能应该根据需要同步该块。 请注意这一点。
当您使用诸如ConcurrentHashMap
之类的synchronizedMap()
Collection或诸如synchronizedMap()
, synchronizedList()
等Collection的方法时,仅Map
/ List
被同步。 为了进一步解释,
考虑,
Map<String, Object> map = new HashMap<>();
Map<String, Object> synchMap = Collections.synchronizedMap(map);
这使得地图的get操作是同步的,而不是其中的对象是同步的。
Object o = synchMap.get("1");// Object referenced by o is not synchronized. Only the map is.
如果要保护Map中的对象,则还必须将代码放入同步块中。 记住这一点很不错,因为在大多数情况下,许多人会忘记保护对象。
看看这个也没有什么信息Collection的syncedMap
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.