同步集合与同步方法?

时间:2015-09-01 07:57:17

标签: java multithreading collections

我有一个包含一个集合的类容器,该集合将由多个线程使用:

synchronized

宣布方法public synchronized void doSomeWithMap(String key, String value)

会更好
Collections.synchronizedMap(map);

或使用标准的线程安全装饰器?

JSON

5 个答案:

答案 0 :(得分:2)

一般来说,同步地图将保护对它的大多数访问,而不必进一步考虑它。但是,“同步映射”对于迭代是不安全的,这可能是一个问题,具体取决于您的用例。 It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views.

如果符合您的使用案例,请考虑使用ConcurrentHashMap

如果此对象的其他状态需要防止并发错误,那么您将需要使用synchronized或Lock

答案 1 :(得分:2)

如果你看一下SynchronizedMap的实现,你会发现它只是一个包含非线程安全映射的映射,它在调用任何方法之前使用了互斥锁

private void makeButtonsListen(Listener listener) {
    for (Button button : aButtons) {
        button.addListener(SWT.MouseDown, listener);
    }
}

如果你想要的只是保护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,那么这个实现就是为你做的。

但是,如果你想要一个可以迭代并由两个或多个线程更新的Map,那就不合适了,在这种情况下你应该使用ConcurrentHashMap

答案 2 :(得分:1)

如果你在doSomeWithMap内做的其他事情如果由不同的线程同时完成(例如,他们更新类级变量)会导致问题,那么你应该同步整个方法。如果不是这种情况,那么您应该使用同步Map以最小化同步锁保留的时间长度。

答案 3 :(得分:1)

如果您的doSomeWithMap方法将多次访问地图 ,则必须同步doSomeWithMap方法。如果访问是显示的put()调用,则最好使用ConcurrentHashMap

请注意,“不止一次”是任何调用,而迭代器本质上是很多“获取”。

答案 4 :(得分:1)

您可能应该根据要求同步块。请注意这一点。

当您使用ConcurrentHashMap等同步收集或synchronizedMap()synchronizedList()等收集方法时,只会同步Map / List 。为了进一步解释,

考虑,

Map<String, Object> map = new HashMap<>();
Map<String, Object> synchMap = Collections.synchronizedMap(map);

这使得地图的获取操作是同步的,而不是其中的对象。

Object o = synchMap.get("1");// Object referenced by o is not synchronized. Only the map is.

如果要保护Map内的对象,则还必须将代码放在synchronized块中。这是值得记住的,因为在大多数情况下,许多人忘记了保护对象。

请看这个小信息Collection's synchronizedMap