目录
首先我们先看下1.7版本的原理
ConcurrentHashMap
是 Java 中的一个线程安全的 HashMap 实现,用于在多线程环境中高效地进行并发操作。在 Java 1.7 中,ConcurrentHashMap
的实现进行了重大的改进,以提高并发性能。下面是 Java 1.7 中 ConcurrentHashMap
的实现原理的详细解释。
1. HashEntrySegmentation
在 Java 1.7 中,ConcurrentHashMap
采用了分段锁的策略,其核心思想是将一个大的 HashMap 分割成多个小的 HashMap,称为 Segment
。每个 Segment
内部其实是一个小的 HashMap,它有自己的锁。当线程访问 ConcurrentHashMap
时,它首先需要根据 hashcode 找到对应的 Segment
,然后在该 Segment
上进行同步操作,而不是在整个 ConcurrentHashMap
上进行同步。这样就可以实现真正的并发性,而不是像 Hashtable
或同步的 HashMap
那样的伪并发性。
2. HashEntry
在每个 Segment
中,存储数据的结构是 HashEntry
,这与 HashMap
中的实现类似。HashEntry
是一个链表结构,用于处理哈希冲突。当两个元素的哈希值相同时,它们会被放在同一个 HashEntry
中。
3. ReentrantLock
每个 Segment
都有一个 ReentrantLock
,用于在修改 HashEntry
时进行同步。这使得在多线程环境中,可以同时对不同的 Segment
进行操作,而不会相互干扰。这就是 ConcurrentHashMap
能够实现高并发性能的关键。
4. put 操作
当执行 put 操作时,首先计算 key 的 hashcode,找到对应的 Segment
,然后在该 Segment
上加锁,最后将数据放入对应的 HashEntry
中。如果当前 HashEntry
中已经有数据,则需要遍历链表,找到合适的位置插入数据。
5. get 操作
get 操作不需要加锁,因为它只是读取数据,不会修改数据。这也是为了提高 ConcurrentHashMap
的读取性能。
6. size 操作
由于 ConcurrentHashMap
是并发的,因此在执行 size 操作时,需要遍历所有的 Segment
,并将每个 Segment
中的元素数量相加。这个过程是需要加锁的,以防止在遍历过程中有其他线程修改数据。
总的来说,Java 1.7 中的 ConcurrentHashMap
通过分段锁的策略,实现了高并发性能。在每个 Segment
内部,其实就是一个小的 HashMap
,这使得 ConcurrentHashMap
在多线程环境中的性能远远超过了 Hashtable
和同步的 HashMap
。
再看下1.8版本的原理
ConcurrentHashMap在1.8中的实现原理与1.7版本相比有了显著的变化。以下是ConcurrentHashMap 1.8实现原理的详解:
数据结构的变化:
在1.8版本中,ConcurrentHashMap不再使用分段锁,而是使用了CAS(Compare-and-Swap)操作和synchronized关键字来实现并发控制。它也引入了红黑树(当链表长度大于一定阈值(默认为8)时,链表就转换为红黑树)作为数据结构,进一步提高搜索速度。
节点结构:
1.8中的节点结构与1.7不同,它使用内部类Node作为最基本的存储单元,这个Node类继承了HashMap中的Entry。当两个节点的key-value相等时,新添加的节点会覆盖原有的节点,这与HashMap中的实现不同。
CAS操作:
CAS操作是一种无锁化的技术,它包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置的值更新为新值B。否则,处理器不做任何操作。整个比较并交换的操作是一个原子操作。在ConcurrentHashMap中,CAS操作主要用于确保对Node节点的操作的线程安全性。
synchronized关键字:
在1.8版本的ConcurrentHashMap中,synchronized关键字被用来修饰某些方法,以实现线程安全的操作。这是在1.8版本中引入的新特性,使得ConcurrentHashMap在保持高并发性能的同时,也能保证线程安全。
总的来说,ConcurrentHashMap 1.8版本通过引入红黑树、使用CAS操作和synchronized关键字,提高了并发性能和搜索速度,同时也保证了线程安全,这是相对1.7版本的主要改进。
总结
区别:
-
1.7用的数组+链表,安全的方式为分段锁
-
1.8用的数组+链表+红黑树,结构和HashMap一致,抛弃了分段锁,采用CAS+自旋以及Synchronized