Say如果有一个synchronized方法并且在该方法中,我更新一个这样的hashmap:
public synchronized void method1()
{
myHashMap.clear();
//populate the hashmap, takes about 5 seconds.
}
现在当method1正在运行并且正在重新填充hashmap时,如果还有其他线程要获取hashmap的值,我认为它们会被阻塞吗?
现在,如果我将hashmap更改为ConcurrentHashMap,而不是使用sync方法,那么行为是什么?
public void method1()
{
myConcurrentHashMap.clear();
//populate the hashmap, takes about 5 seconds.
}
如果我使用Collections.synchronizedMap怎么办?它是一样的吗?
答案 0 :(得分:13)
CHM(ConcurrentHashMap),而不是同步公共锁上的每个方法,限制对单个线程的访问 它一次使用一种称为锁定条带的更细粒度的锁定机制,以允许更大程度的共享访问。任意多的阅读线程 可以同时访问地图,读者可以同时访问地图 作家和有限数量的作家可以同时修改地图。结果 并发访问下的吞吐量要高得多,性能损失很小 单线程访问。 ConcurrentHashMap以及其他并发集合进一步改进 通过提供不抛出的迭代器来实现同步集合类 ConcurrentModificationException,从而消除了锁定集合的需要 在迭代期间。
与所有改进一样,仍有一些权衡。方法的语义 在整个Map上运行,例如size和isEmpty,略有不同 削弱以反映集合的并发性质。由于尺寸的结果 在计算时它可能已经过时,它实际上只是一个估计,所以大小 允许返回近似值而不是精确计数。虽然起初这个 可能看起来很令人不安,实际上像size和isEmpty这样的方法远没那么有用 并发环境,因为这些数量是移动目标。
其次,Collections.synchronizedMap
这只是带有同步方法的简单HashMap - 我把它称为对CHM弃用的dute
答案 1 :(得分:8)
如果您希望对HashMap
同步进行所有读写操作,则需要将synchronize
放在访问HashMap
的所有方法上;仅阻止一种方法是不够的。
ConcurrentHashMap
允许线程安全访问您的数据而无需锁定。这意味着您可以在一个线程中添加/删除值,同时在另一个线程中获取值而不会遇到异常。另请参阅documentation of ConcurrentHashMap
答案 2 :(得分:0)
volatile private HashMap map = newMap();
private HashMap newMap() {
HashMap map = new HashMap();
//populate the hashmap, takes about 5 seconds
return map;
}
public void updateMap() {
map = newMap();
}
读者看到一个常量映射,因此读取不需要同步,也不会被阻止。