ConcurrentHashMap
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
implements ConcurrentMap<K, V>, Serializable
它实现了ConcurrentMap这个接口.这个接口有四个方法
putIfAbsent(K,V):
它的伪代码实现
* if (!map.containsKey(key))
* return map.put(key, value);
* else
* return map.get(key);</pre>
如果map里面不包含(Absent)这个key的话,才可以把这个放进去
如果map里面有这个key了,直接返回这个key.
remove(K,V):
它的伪代码实现
* if (map.containsKey(key) && map.get(key).equals(value)) {
* map.remove(key);
* return true;
* } else return false;</pre>
这个方法的参数时两个,key和value,只有当两个都对上了才进行remove
replace(key,oldValue,newValue):
它的伪代码实现
* if (map.containsKey(key) && map.get(key).equals(oldValue)) {
* map.put(key, newValue);
* return true;
* } else return false;</pre>
这个方法有三个参数,key和oldValue和newValue,
只有当key和oldValue都对上的时候才将newValue进行替换
replace(key,value):
它的伪代码实现
* if (map.containsKey(key)) {
* return map.put(key, value);
* } else return null;</pre>
这个方法有两个参数如果map中含有key就用value进行替换.
ConcurrentHashMap的数据结构是:一个segment数组.这个数组大小最大为16
同时最多16个进行写,可以很多个读.
static final class Segment<K,V> extends ReentrantLock implements Serializable
transient volatile HashEntry<K,V>[] table;
每个segment是一个继承了重入锁的类,里面是一个使用了volatile的HashEntry<k,v> table.
Put(key,value)
首先会确认value是不是为空,如果为空就抛异常
通过key找到segment在数组中的索引位置.
然后遍历segment下面的table,此时要进行tryLock()(使用trylock不是lock因为可能有其他线程在访问).
接下来类似hashmap的添加.找不到key的话进行头插.
get(key)
时候不会进行加锁,因为segment里面的table使用的是volatile,所以读的时候数据被修改了也无妨.