9

假设如果有一个同步方法,并且在该方法中,我会更新一个哈希图,如下所示:

public synchronized void method1()
{
    myHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

现在当method1正在运行并且hashmap正在重新填充时,如果有其他线程试图获取hashmap的值,我假设它们会被阻塞?

现在而不是使用同步方法,如果我将 hashmap 更改为 ConcurrentHashMap 如下所示,行为是什么?

public void method1()
{
     myConcurrentHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

如果我使用 Collections.synchronizedMap 怎么办?是一样的吗?

4

3 回答 3

14

CHM(ConcurrentHashMap),它不是在一个公共锁上同步每个方法,一次限制对单个线程的访问,而是使用一种称为锁条带的更细粒度的锁定机制来允许更大程度的共享访问。任意多个读线程可以并发访问map,reader可以和writer并发访问map,有限数量的writer可以并发修改map。结果是并发访问下的吞吐量要高得多,而单线程访问的性能损失很小。ConcurrentHashMap 与其他并发集合一起,通过提供不抛出 ConcurrentModificationException 的迭代器进一步改进了同步集合类,从而消除了在迭代期间锁定集合的需要。

与所有改进一样,仍有一些权衡。对整个 Map 进行操作的方法的语义,例如 size 和 isEmpty,已经略微弱化以反映集合的并发性。由于 size 的结果在计算时可能已经过时,它实际上只是一个估计值,因此 size 允许返回近似值而不是精确计数。虽然起初这似乎令人不安,但实际上像 size 和 isEmpty 这样的方法在并发环境中的用处要小得多,因为这些量是移动的目标。



第二,Collections.synchronizedMap

它只是带有同步方法的简单 HashMap - 我称它为 CHM 已弃用

于 2012-09-27T19:26:31.553 回答
8

如果您想对您的同步进行所有读写操作HashMap,您需要将synchronize所有方法放在访问HashMap; 仅仅阻止一种方法是不够的。

ConcurrentHashMap允许线程安全地访问您的数据而无需锁定。这意味着您可以在一个线程中添加/删除值,同时在另一个线程中获取值而不会遇到异常。另请参阅ConcurrentHashMap 的文档

于 2012-09-27T19:30:57.567 回答
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();
}

读取器看到一个常量映射,因此读取不需要同步,也不会被阻塞。

于 2012-09-27T19:32:54.947 回答