concurrentHashMap和hashtable的区别,concurrentHashMap在各个版本的jdk中实现有什么不同

这里首先先说一下hashtable和hashMap 的区别:

    1.HashMap是非synchronized,hashTable 是synchronized;

    2.HashMap可以接受为Null的Key和value,而hashtable不能接受;(在hashtable中会提示空指针异常NullPointerException)

这里再说一下concurrentHashMap:

jdk1.7

一下根据jdk文档翻译

hashtable 支持检索的一致性和更新的一致性,然而,尽管所有的操作都是线程安全的,更新操作都需要一致性锁,这个操作会使得锁住整个表时是都不可以进行操作的。相对于hashtable而言concurrentHashMap 是完全可以操作的依赖于他的线程安全而不是他的同步特性。检索操作例如 get操作通常都不会阻塞,更多的重叠的操作是更新操作,例如 put和remove。检索操作反映的是最近完成状态的一个结果,而更新操作更依赖于发生变化的过程。对于整体的操作例如 putAll 和clear,并发检索的操作可能会受到插入或者删除entries的影响。类似的,迭代器和枚举器返回的元素也会受hashtable在某个时间点的状态的影响。这些都不会导致 ConcurrentModificationException. 不管怎么样,迭代器Iterators被设计成在同一时刻只能被一个线程访问的。(也就是说iterator都是线程安全的???)

引入 concurrentLevel 也就是段segment的概念,默认值是16,这样这些表被划分然后被一定数量的并发更新操作时互相就不会存在竞争了,因为放置过程中在hashtables中是大体随机的,在实际的并发过程中是不同的。比较理想的情况是,你可以选定一个值去顾及更多的并发线程去进行修改操作。使用一个比所需要的值高很多的值可能会浪费空间和时间,而使用一个显然低很多的值可能导致线程争用。更加显著高效的利用空间和时间从而减少了并发线程之间的竞争,相差数量级的高估和低估都会带来显著的影响。当仅有一个线程将执行修改操作,而其他所有线程都只是执行读取操作时,才认为某个值是合适的。此外,重新调整此类或其他任何种类哈希表的大小都是一个相对较慢的操作,因此,在可能的时候,提供构造方法中期望表大小的估计值是一个好主意。

concurrentHashMap实现了Map和Iterator中的所有方法,类似hashtable而不类似HashMap,不允许用Null用于设置Key或者value。

可以参考这个 https://my.oschina.net/hosee/blog/639352 帖子,详细的介绍了其中的原理。

那么,1.6和1.7中有什么不同呢?

1.创建segment的过程中有些不同,和jdk6相比,在jdk7中,除了第一个segment之外,其余的segment的创建都是采用延时创建的方式:也就是说在put操作之前都需要先判断key对应的segment是否已经创建,如果没有创建的话,使用ensureSegment来进行创建,这里并没有使用锁的概念来创建,而是使用了Unsafe对象的getObjectVolatile()提供的原子读语义结合CAS来确保Segment创建的原子性。(这里unsafe)



你可能感兴趣的:(基础知识)