多线程环境中的Hashmap和哈希表

时间:2009-09-01 10:53:27

标签: java multithreading thread-safety hashtable hashmap

我对这两个集合在多线程环境中的行为方式感到困惑。

哈希表是同步的,这意味着没有2个线程会同时更新它的值吗?

5 个答案:

答案 0 :(得分:12)

查看ConcurrentHashMap的线程安全地图。

它们提供HashTable的所有功能,其性能非常接近HashMap。

通过代替使用地图宽锁获得性能,该集合默认维护一个包含16个锁的列表,每个锁用于锁定地图的单个存储桶。您甚至可以配置存储桶数量:)根据您的数据调整此数据可以提高性能。

我不能在Brian Goetz的推荐下推荐足够的Java Concurrency in Practice http://jcip.net/

每当我读到它时,我仍然会学到新东西。

答案 1 :(得分:3)

另请注意,Hashtable和Collections.synchronizedMap仅对单个操作安全。任何涉及多个密钥或check-then-act的操作都需要是原子的,并且需要额外的客户端锁定。

例如,如果没有额外的锁定,则无法编写以下任何方法:

  • 在两个不同的键上交换值:swapValues(Map, Object k1, Object k2)

  • 将参数附加到键的值:appendToValue(Map, Object k1, String suffix)

是的,所有这些都包含在JCIP中: - )

答案 2 :(得分:2)

确切地说,HashTable是同步的,这意味着在多线程环境中使用它是安全的(许多线程访问相同的HashTable)如果两个线程试图在同一时间更新哈希表,其中一个将不得不等待其他线程完成了他的更新。

HashMap未同步,因此速度更快,但您可能在多线程环境中遇到问题。

答案 3 :(得分:0)

是的,所有方法都是以原子方式完成的,但value()方法不是(参见docs)。

Paul比我推荐java.util.concurrent包更快,它为多线程环境提供了非常精细的控制和数据结构。

答案 4 :(得分:0)

哈希表是同步的,但它们是一个旧的实现,你几乎可以说它已经被弃用了。此外,它们不允许空键(也许不是空值?不确定)。

一个问题是尽管每个方法调用都是同步的,但大多数有趣的操作都需要多个调用,因此您必须围绕多个调用进行同步。

通过调用:

,可以为HashMaps获得类似的同步级别
Map m = Collections.synchronizedMap(new HashMap());

在同步方法调用中包装映射。但这与Hashtable具有相同的并发性缺点。

正如Paul所说,ConcurrentHashMaps为原子更新提供了其他有用的方法的线程安全映射。