该类并非在每一个方法上加上同步锁,而是使用分段锁。迭代时不会抛出ConcurrentModificationException,因此不须要在迭代的时候,加上同步锁 。不过在获取size和isEmpty的时候,可能只是个估计值,而不是精确值。java
一个ConcurrentHashMap由多个segment组成,每个segment都包含了一个HashEntry数组的hashtable, 每个segment包含了对本身的hashtable的操做,好比get,put,replace等操做,这些操做发生的时候,对本身的hashtable进行锁定(分段锁)。因为每个segment写操做只锁定本身的hashtable,因此可能存在多个线程同时写的状况,性能无疑好于只有一个hashtable锁定的状况。数组
迭代期间不须要加锁。其基本思路是,从一开始你们都在共享同一个内容,当某我的想要修改这个内容的时候,才会真正把内容Copy出去造成一个新的内容而后再改,这是一种延时懒惰策略。并发
通俗的理解是当咱们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,而后新的容器里添加元素,添加完元素以后,再将原容器的引用指向新的容器。这样作的好处是咱们能够对CopyOnWrite容器进行并发的读,而不须要加锁,由于当前容器不会添加任何元素。因此CopyOnWrite容器也是一种读写分离的思想,读和写不一样的容器。下面是增长的时候的源码: 性能
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
因为添加元素的时候,会拷贝出一个副本再添加,所以这个list只适用于遍历多,修改少的场景。this