Java ConcurrentHashMap是否需要包装在同步块中?

Java ConcurrentHashMap是否需要包装在同步块中?,java,synchronized,concurrenthashmap,Java,Synchronized,Concurrenthashmap,ConcurrentHashMap上的所有非检索操作(put(),remove()等)是否都需要包装在同步(this)块中?我知道所有这些操作都是线程安全的,那么这样做有什么真正的好处/需要吗?使用的唯一操作是put()和remove() protectedfinal-Map-mapDataStore=new-ConcurrentHashMap(); public void updateDataStore(最终字符串键、最终字符串值){ ... 已同步(此){ mapDataStore.put(

ConcurrentHashMap上的所有非检索操作(
put()
remove()
等)是否都需要包装在
同步(this)
块中?我知道所有这些操作都是线程安全的,那么这样做有什么真正的好处/需要吗?使用的唯一操作是
put()
remove()

protectedfinal-Map-mapDataStore=new-ConcurrentHashMap();
public void updateDataStore(最终字符串键、最终字符串值){
...
已同步(此){
mapDataStore.put(键,值);
}
...
}

不,这样做会失去
ConcurrentHashMap
的好处。您也可以将
HashMap
synchronized
synchronizedMap()
一起使用来锁定整个表(这是在
synchronized
中包装操作时所做的,因为所暗示的监视器是整个对象实例。)

ConcurrentHashMap
的目的是通过允许在不锁定整个表的情况下对表进行并发读/写来提高并发代码的吞吐量。该表通过使用锁条带化(多个锁而不是一个锁,每个锁分配给一组散列桶,请参见Goetz等人的内容)在内部支持这一点

使用
ConcurrentHashMap
后,所有标准映射方法(
put()
remove()
,等等)都会由于实现中的锁条带化等而变得原子化。唯一的折衷是像
size()
isEmpty()
这样的方法可能不一定会返回准确的结果,因为它们的唯一方法是让所有操作锁定整个表


该接口还添加了新的原子复合操作,如
putIfAbsent()
(仅当键不在映射中时才放入内容),
remove()
同时接受键和值(仅当其值等于您传递的参数时才删除条目),等等。这些操作过去需要锁定整个表,因为它们需要两个方法调用才能完成(例如,
putIfAbsent()
需要同时调用
containsKey()
put()
,如果您再次使用标准的
Map
实现,则需要将它们封装在一个
synchronized
块中。),通过避免锁定整个表,使用这些方法可以获得更大的吞吐量。

同步这些操作在这里没有好处-如果不需要同步,实际上会降低性能


创建
ConcurrentHashMap
的原因是,同步映射(可以像问题中那样手动实现,也可以用
集合的常规方式实例化。synchronizedMap(map)
)在被多个线程访问时显示出较差的性能。Put和get操作被阻塞,因此所有其他线程都必须等待,并且不能同时访问映射。另一方面,
ConcurrentHashMap
——顾名思义——允许并发访问。如果添加同步,您将失去这一优势。

如果代码块同时包含containsKey()和put()方法,该怎么办?是否应该同步?@gaurav,可能应该同步。但是我宁愿使用
putIfAbsent
computeIfAbsent
(这两种方法都是ConcurrentMap的原子操作)而不是同步。2:如果使用Java 1.7,那么选项会是什么?
protected final Map<String, String> mapDataStore = new ConcurrentHashMap<String, String>();

public void updateDataStore(final String key, final String value) {
    ...
    synchronized (this) {
        mapDataStore.put(key, value);
    }
    ...
}