CopyOnwriteArrayList

ArrayList: ConcurrentModificationException concurrent modification abnormalities

public class CopyonwriteArraylist_Test {
    public static void main(String[] args) {
        List<String > list=new ArrayList();
        for (int i=0; i<=10; i++){new Thread(()->{list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); },String.valueOf(i)).start(); }}}Copy the code

Solution:

  • List list=new Vector();
  • List list=Collections.synchronizedList();
  • List list=new CopyOnWriteArrayList<>();

Why is CopyOnWriteArrayList thread-safe

public boolean add(E e) {
        final ReentrantLock lock = this.lock; // Use ReentrantLock to ensure that only one thread makes changes
        lock.lock();
        try {
        // Copy while writing
            Object[] elements = getArray();// Get the old array
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);// Create a new array with len+1 and copy the old array
            newElements[len] = e; // Add a new element to the end of the new array
            setArray(newElements);
            return true;
        } finally{ lock.unlock(); }}@SuppressWarnings("unchecked")
    // Read without locking
    private E get(Object[] a, int index) {
        return (E) a[index];
    }
Copy the code

The advantages and disadvantages

  • CopyOnWrite container, copy while writing, is the idea of separate reads and writes.
  • Read without locking, concurrent read can improve concurrency
  • The lock is only used for modification or deletion, and the operation on the new array does not affect the read
  • Since the read is not locked, it is possible for a thread to modify the data while reading, thus reading old data, which is weak consistency
  • It takes up memory. When you write, new objects are created and added to the new container, while the objects in the old container are still in use, so there are two pieces of object memory. If the memory usage is large, ConcurrentHashMap is recommended

Difference from Vector

  • Vector is roughly synchronized and has low concurrency. A CopyOnWrire locks only when it is being modified, making it easy to read

CopyOnwriteArraySet

  • A HashSet is essentially the key of a Hash Map. The key of a Hashmap is used to ensure uniqueness and also causes disorder.
  • CopyOnwriteArraySet is actually done by calling CopyOnwriteArrayList.
 public HashSet(a) {
        map = new HashMap<>();
    }
 private static final Object PRESENT = new Object();
 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
Copy the code
public CopyOnWriteArraySet(a) {
        al = new CopyOnWriteArrayList<E>();
    }
public boolean add(E e) {
        return al.addIfAbsent(e);
    }

Copy the code

ConcurrentHashMap

  • HashMap is thread-unsafe
  • HaspTable is thread-safe, but simple and crude synchronization, low efficiency

ConcurrentHashMap

Reference: zhuanlan.zhihu.com/p/31614308

ConcurrentHashMap maintains a segments array as follows. ConcurrentHashMap is a two-level hash table. Under a total hash table, there are several subhash tables.

  • Different segments have different locks, which reduces lock granularity while ensuring thread safety and makes concurrent operations more efficient.
  • The same Segment is unlocked only when it is read and written
  • After 1.8 directly use Node array + linked list + red-black tree data structure to achieve, concurrency control using built-in Synchronized and CAS to operate, a lock only locks a linked list.

Reference:Blog.csdn.net/qq_41884976…