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…