76-85行 注释:这里主要讲的是同为线程安全的Hash,HashTable和ConcurrentHashMap的区别。ConcurrentHashMap(下文用本类指代)虽然是线程安全的,但是检索操作(比如get,是不保证加以锁的),并且本类没有任何操作用于锁住整个类实例的表。本类并不是以同步锁(synchronize)来保证线程安全的,而是它本身操作的性质(CAS无锁化同步)。
87行-106行 注释:因为前面提到本类中的检索操作是不加互斥锁的,所以可能在读操作的时候会与写操作(put/remove)发生重叠(即在多线程情况下出现的)。这时候检索的结果应该是最近一次写操作完成后的结果。而在大多数情况下,写操作应该是比读操作先完成的(笔者猜想可能是优先级的问题。)而在大批量操作(比如putAll/clear/size/isEmpty/containsValue),并发执行get方法得到的是插入/删除节点一部分键值对,因此上述操作只有在单线程情况下能保证正确,否则只能代表多线程情况下的瞬时状态。仅供参考作为评估,而不应该用于程序的控制。同样的,在大批量操作的情况下创建的迭代器/字符分割器/枚举器,反应的结果是创建迭代器时hash表的状态。注意,本类不迭代器并不抛出快速失败异常。
解析:(1)本类的迭代器不抛出“快速失败”异常。(2)聚集类操作(putAll/clear/size/isEmpty/containsValue)在多线程情况下得到的可能是本类对应一部分的结果。
108-128行 注释:这里和前面记录的hashmap就很像了。首先是介绍了一下初始容量和装载因子,以及它们的作用。由于我们知道resize/rehash操作是消耗很大的,应该尽量避免这种操作。对于实现了Compareable接口的类,会采用compareTo方法进行比较保证有序。还提到了以前JDK版本本类方法中提供一种参数的构造函数concurrencyLevel指定锁段长度(最大65535)
解析:在JDK 1.7的时候,通过的不是CAS而是锁段,来执行操作。这是1.8和1.7的最大的一个区别。这也是为什么hashtable基本不使用,都使用本类的原因。
锁分段技术:HashTable在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁,假如容器里有多把锁,每一把锁用于锁容器其中一部分的数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术.首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问.
同时,本类也可以用作数据库缓存(类似于Redis),只是本类主要是用在短时间访问量高的情况,map可以作为内存式缓存,短时间访问量高可以使用