繁体   English   中英

同步收集与同步方法?

[英]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;
  }
}

如果您想要保护的是getput ,那么此实现将为您完成它。

但是,如果您希望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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM