JAVA copy (Copy-On-Write) Map implement write

https://www.cnblogs.com/hapjin/p/4840107.html

 

1. What is the copy (Copy-On-Write) container write?

When writing copy means: In the context of concurrent access, when you need to modify the elements in JAVA Containers, does not directly modify the vessel, but first make a copy, make changes on the copy. After editing, the references point to the original container to the new container (a copy of the container).

 

2. Copy the impact of write

① Because not modify the original container, the container only modify the copy. Thus, concurrently can be read on the original container. Secondly, to achieve the separation of read and write operations, read operations occur on the original container, write occurs on a copy of the container.

② data consistency: read the thread may not be immediately read to the newly revised data, because the modification operation occurs on a copy. But eventually modify the operation will be completed and update the container, so this is the ultimate consistency.

 

3, provides CopyOnWriteArrayList CopyOnWriteArraySet class and class in the JDK, but did not provide an implementation of CopyOnWriteMap. Therefore, it is possible to achieve a reference CopyOnWriteArrayList own CopyOnWriteHashMap

This is mainly achieved during a write operation, how to ensure thread safety.

Copy the code

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable{

    private volatile Map<K, V> internalMap;
    
    public CopyOnWriteMap() {
        internalMap = new HashMap <K, V> (100); // Initial size should be specified according to the application
    }
    
    @Override
    public V put(K key, V value) {
        synchronized (this) {
            Map <K, V> newMap = new HashMap <K, V> (internalMap); // copy a new HashMap
            V val = newMap.put (key, value); // write operation is performed in the new HashMap
            internalMap = newMap; // references to the original Map New Map
            return val;
        }
    }
    
    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        synchronized (this) {
            Map<K, V> newMap = new HashMap<K, V>(internalMap);
            newMap.putAll(m);
            internalMap = newMap;
        }
        
    }
    
    @Override
    public V get(Object key) {
        V result = internalMap.get(key);
        return result;
    }
    ......//other methods inherit from interface Map
}

Copy the code

As can be seen from the above, to put () and the putAll (), the need to lock. Read action is required, such as the get (Object key). Thus, when a thread needs to put a new element, first lock the current CopyOnWriteMap objects, and copy a new HashMap, while others read a thread because there is no lock, you can continue to access the original HashMap.

 

4, application scenarios

CopyOnWrite container suitable for reading and writing little scenes. Because the write operation, the need to copy a container, resulting in a large memory overhead, but also need to grasp the size of the initial container depending on the application.

Not suitable for strong data consistency occasion. After the data modification if required can be read immediately, you can not use copy-on-write technology. Because it is the ultimate consistency.

Summary: replication technologies write is a good means of improving concurrency.

 

5. Why is there COW?

Common actions on collections (ArrayList, HashMap) are: add elements to the collection, remove elements through the elements and then set in a certain operation. When performing these operations on a collection object will trigger multiple threads concurrently ConcurrentModificationException, such as thread traversing ArrayList in A for-each, the thread B at the same time removing elements in the ArrayList, you may throw ConcurrentModificationException, can a locking when thread traversing ArrayList, but the traversal operation is a common operation, then the lock will affect the performance of the program, thus selected for-each traversing ArrayList lock but not when there is a plurality of threads modifies ArrayList throw ConcurrentModificationException, therefore, this is a trade-off on a design.

In order to cope with multi-threaded modify this situation, a strategy that is the subject of this "copy-on-write" mechanism; Another strategy is to: thread-safe container class:

ArrayList--->CopyOnWriteArrayList

HashMap--->ConcurrentHashMap

The ConcurrentHashMap not "Copy" from this point of view to deal with the multi-threaded concurrent modification, but the introduction of segmented lock (JDK7); CAS, Lock (JDK11) to solve the problem of multi-threaded concurrent modification.

 

References:

Copy-On-Write talk container of concurrent -Java

Java HashMap 10 series collection of details (source code parsing) and use the sample

Guess you like

Origin blog.csdn.net/lppl010_/article/details/91904043