【发布时间】:2009-09-01 10:53:27
【问题描述】:
我对这两个集合在多线程环境中的行为感到非常困惑。
哈希表是同步的,这意味着不会有 2 个线程同时更新它的值,对吧?
【问题讨论】:
标签: java multithreading thread-safety hashtable hashmap
我对这两个集合在多线程环境中的行为感到非常困惑。
哈希表是同步的,这意味着不会有 2 个线程同时更新它的值,对吧?
【问题讨论】:
标签: java multithreading thread-safety hashtable hashmap
查看ConcurrentHashMaps 以获得线程安全映射。
它们提供了 HashTable 的所有功能,性能非常接近 HashMap。
通过不使用地图范围的锁来获得性能,该集合默认维护一个包含 16 个锁的列表,每个锁用于锁定地图的单个存储桶。您甚至可以配置存储桶的数量 :) 调整这可以根据您的数据提高性能。
Brian Goetz 的 Java Concurrency in Practice 我不能推荐足够多的东西 http://jcip.net/
每次阅读时我都会学到一些新东西。
【讨论】:
没错,HashTable 是同步的,这意味着在多线程环境中使用它是安全的(许多线程访问同一个 HashTable)如果两个线程同时尝试更新 hashtable,其中一个将不得不等待其他线程完成他的更新。
HashMap 不同步,所以比较快,但是在多线程环境下会出现问题。
【讨论】:
还要注意 Hashtable 和 Collections.synchronizedMap 仅对单个操作是安全的。任何涉及多个键或 check-then-act 的操作都需要是原子的,不是,并且需要额外的客户端锁定。
例如,如果没有额外的锁定,您不能编写以下任何方法:
交换两个不同键的值:swapValues(Map, Object k1, Object k2)
将参数附加到键的值:appendToValue(Map, Object k1, String suffix)
是的,所有这些都包含在 JCIP 中:-)
【讨论】:
ConcurrentMap 为Map 添加了一些非常有用的方法。
是的,所有方法都是原子完成的,但 values() 方法不是(请参阅docs)。
Paul 比我更快地向您推荐了 java.util.concurrent 包,它为您提供了适用于多线程环境的非常精细的控制和数据结构。
【讨论】:
哈希表是同步的,但它们是一个旧的实现,您几乎可以说它已被弃用。此外,它们不允许空键(也许也不是空值?不确定)。
一个问题是,虽然每个方法调用都是同步的,但大多数有趣的操作需要多个调用,因此您必须围绕多个调用进行同步。
通过调用 HashMap 可以获得类似级别的同步:
Map m = Collections.synchronizedMap(new HashMap());
它在同步方法调用中包装了一个映射。但这与 Hashtable 有相同的并发缺点。
正如 Paul 所说,ConcurrentHashMaps 为线程安全映射提供了额外有用的原子更新方法。
【讨论】: