已经有一段时间了,因为我已经将哈希表用于任何重要的事情,但我似乎记得同步的get()和put()方法。
JavaDocs没有反映这一点。他们只是说Hashtable类是同步的。我能假设什么?如果多个线程同时访问哈希表(假设它们没有修改相同的条目),则操作将成功,对吧?我想我要问的是“java.util.Hashtable线程安全吗?”
请指导我摆脱这个问题...
答案 0 :(得分:12)
它是线程安全的,因为get,put,contains方法等是同步的。此外,无论他们正在修改哪些条目,多个线程都无法同时访问哈希表。
编辑 - 修改为包含同步使得哈希表内部线程安全的条件,因为它是原子地修改的;它不能防止由多个线程并发访问哈希表引起的外部代码中的竞争条件。
答案 1 :(得分:10)
对于一般用法,它是线程安全的。
但是你必须明白,它使你的应用程序逻辑在线程安全。对于例如考虑实现在地图中放置一个值,如果它不存在的话。 这个成语叫做putIfAbsent。很难单独使用HashTable以线程安全的方式实现它。类似地,对于习语替换(k,V,V)。
因此,对于某些习语,例如 putIfAbsent 和替换(K,V,V),我建议使用ConcurrentHashMap
答案 2 :(得分:3)
不推荐使用Hashtable。算了吧。如果要使用同步集合,请使用Collections.syncrhonize *()包装器来实现此目的。但不推荐这些。在Java 5中,已经实现了6个新的并发算法。写时复制,CAS,无锁算法。 对于Map接口,有两个并发实现。 ConcurrentHashMap(并发哈希映射)和ConcurrentSkipListMap - 并发排序映射实现。
第一个针对阅读进行了优化,因此即使在更新表时,检索也不会阻止。与同步包装器相比,写入的工作速度要快得多,因此ConcurrentHashMap不是一个而是一组表,称为段。它可以由构造函数中的最后一个参数来管理:
public ConcurrentHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel);
ConcurrentHashMap在高度并发的上下文中是必不可少的,它的性能远远超过任何可用的替代方案。
答案 3 :(得分:2)
我问的是“java.util.Hashtable线程安全吗?”。
是Hashtable是线程安全的,如果您的应用程序中不需要线程安全,那么请通过HashMap,如果需要线程安全的实现,那么建议使用ConcurrentHashMap代替Hashtable。
答案 4 :(得分:1)
没有。只有在方法同步的情况下才是'threadsafe'。但是它通常不是线程安全的,并且它不能,因为导出内部状态的类(例如Iterators或Enumerations)也需要使用内部状态进行同步。这就是为什么新的Collections类不同步,因为Java设计者认识到线程安全取决于类的用户,而不是类本身。
答案 5 :(得分:1)
请注意,很多答案都说明Hashtable是同步的。但这会给你一点点。访问器/ mutator方法上的同步将阻止两个线程同时添加或从地图中删除,但在现实世界中,您经常需要额外的同步。
即使迭代Hashtable的条目也不是线程安全的,除非您还通过其他同步保护Map不被修改。
答案 6 :(得分:0)
如果您查看Hashtable代码,您将看到方法已同步,例如:
public synchronized V get(Object key)
public synchronized V put(K key, V value)
public synchronized boolean containsKey(Object key)
您可以继续按下控制键(mac命令),然后单击eclipse中的任何方法名称转到java源代码。
答案 7 :(得分:0)
与新的集合实现不同, Hashtable是同步的。 * 如果不需要线程安全的实现,建议使用HashMap *代替Hashtable。如果需要线程安全的高度并发实现,则建议使用 ConcurrentHashMap代替Hashtable。
http://download.oracle.com/javase/7/docs/api/java/util/Hashtable.html
答案 8 :(得分:-1)
是的,Hashtable线程安全,因此任何时候只有一个线程可以访问哈希表
另一方面,HashMap不是线程安全的(因此“更快”)。