ConcurrentHashMap 和 Hashtable 的区别是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
从原理上分析,Hashtable 实现并发安全的原理是通过 synchronized 关键字,从源码角度,以 clear() 方法为例,代码如下:
public synchronized void clear() { Entry<?,?> tab[] = table; modCount++; for (int index = tab.length; --index >= 0; ) tab[index] = null; count = 0; }
clear() 方法是被 synchronized 关键字所修饰的,同理其他的方法例如 put、get、size 等,也同样是被 synchronized 关键字修饰的。之所以 Hashtable 是线程安全的,是因为几乎每个方法都被 synchronized 关键字所修饰了,这也就保证了线程安全。
Collections.SynchronizedMap(new HashMap()) 的原理和 Hashtable 类似,也是利用 synchronized 实现的。
而 ConcurrentHashMap 实现的原理,却有大大的不同
本质上它实现线程安全的原理是利用了 CAS + synchronized + Node 节点的方式,这和 Hashtable 的完全利用 synchronized 的方式有很大的不同。
因为它们在线程安全的实现方式上的不同,导致它们在性能方面也有很大的不同。当线程数量增加的时候:
Hashtable 的性能会急剧下降,因为每一次修改都需要锁住整个对象,而其他线程在此期间是不能操作的。不仅如此,还会带来额外的上下文切换等开销,所以此时它的吞吐量甚至还不如单线程的情况。
而在 ConcurrentHashMap 中,就算上锁也仅仅会对一部分上锁而不是全部都上锁,所以多线程中的吞吐量通常都会大于单线程的情况,也就是说,在并发效率上,ConcurrentHashMap 比 Hashtable 提高了很多。
Hashtable(包括 HashMap)不允许在迭代期间修改内容,否则会抛出ConcurrentModificationException 异常,其原理是检测 modCount 变量,迭代器的 next() 方法的代码如下:
public T next() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); }
next() 方法中,会首先判断 modCount 是否等于 expectedModCount。其中 expectedModCount 是在迭代器生成的时候随之生成的,并且不会改变。
它所代表的含义是当前 Hashtable 被修改的次数,而每一次去调用 Hashtable 的包括 addEntry()、remove()、rehash() 等方法中,都会修改 modCount 的值。这样一来,如果我们在迭代的过程中,去对整个 Hashtable 的内容做了修改的话,也就同样会反映到 modCount 中。这样一来,迭代器在进行 next 的时候,也可以感知到,于是它就会发现 modCount 不等于 expectedModCount,就会抛出 ConcurrentModificationException 异常。
所以对于 Hashtable 而言,它是不允许在迭代期间对内容进行修改的。
相反,ConcurrentHashMap 即便在迭代期间修改内容,也不会抛出ConcurrentModificationException。
如果我们有并发的场景,那么使用 ConcurrentHashMap 是最合适的,Hashtable 已经不再推荐使用。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。