該類並非在每一個方法上加上同步鎖,而是使用分段鎖。迭代時不會拋出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