Copyonwritearraylist Overview
Copyonwritearraylist is A thread-safe variant of ArrayList.
The difference between copyonwritearraylist and ArrayList is whether arrays and locking are copied.
Copyonwritearraylist as the name implies is a copy of the ArrayList, which means that when modifying the elements of the container, not directly on the original array, but the first copy of an array, It is then modified on the copied array, and its reference is assigned to the reference of the original array after the modification. This represents a read-write separation so that we can read the container at any time.
member Variables
Here are a few common features to parse:
Transient final reentrantlock lock = new Reentrantlock ();//This is the lock attribute in copyonwritearraylist, ensuring that only one thread can come in when updating the original array.
Private volatile transient object[] array;
This is the original array, and we find that the difference between ArrayList is that it adds the volatile attribute.
What is the use of this?
Volaile is equivalent to a weak level of synchronized, provides visibility that is visible to each thread in a multithreaded execution environment, which ensures that all threads get the same data.
Locks provide two levels of mechanism: mutex and visible
Mutual exclusion is that when a thread modifies one of the data, another thread cannot access the data.
It can be seen that one thread modifies one data and the other thread gets the same value. This means that all threads can automatically get the latest value for volatile.
So we can say that synchronized is atomic when the array is guaranteed to write, and the volatile guarantees read The visibility of the array.
--------------------------------------------------------------------------------------------------------------- -------------
Returns the array final object[] GetArray () { return array; } //array copy final void SetArray (object[] a) { array = A; }
Read:
/** * {@inheritDoc} * * @throws indexoutofboundsexception {@inheritDoc} * /public E get (int Index) { return (E) (GetArray () [index]); } No locks are added to the read, and arrays are not copied.
Write:
Modifies a value on the array to the specified element public E set (int index, e element) {final Reentrantlock lock = This.lock;lock.lock (); try {O bject[] elements = GetArray (); Save old value Object OldValue = Elements[index]; if (oldValue! = Element) {int len = elements.length; Copy an array of equal lengths to the original array object[] newelements = arrays.copyof (elements, Len); Changes the value of the specified subscript on the copy array newelements[index] = element; Let the reference in the member variable point to the Copy array SetArray (newelements); } else {//not quite a no-op; ensures volatile write semanticssetarray (elements); } return (E) OldValue;} finally {Lock.unlock ();} }//Add Element public boolean add (E e) {final Reentrantlock lock = This.lock;lock.lock (); try {object[] Eleme NTS = GetArray (); int len = elements.length; <span style= "White-space:pre" ></span>//copy an array larger than the original array length of a unit object[] newelements = arrays.copyof (elements , Len + 1); <span style= "White-space:pre" ></span>//add the specified element at the end newelements[len] = e; <span style= "whitE-space:pre "></span>//Set reference SetArray (newelements); return true;} finally {Lock.unlock ();} }//Remove the element that specifies the subscript public E Remove (int index) {final Reentrantlock lock = This.lock;lock.lock (); try {object[] elements = GetArray (); int len = elements.length; <span style= "White-space:pre" ></span>//save old value Object OldValue = Elements[index]; int nummoved = len-index-1; if (nummoved = = 0) <span style= "White-space:pre" ></span>//Remove the value at the end SetArray (arrays.copyof (elements, len-1)) ; else {<span style= "white-space:pre" ></span>//Create new array object[] newelements = new Object[len-1]; <span style= "white-space:pre" ></span>//Copy index value system.arraycopy (elements, 0, newelements, 0, index) starting from 0 ); <span style= "White-space:pre" ></span>//Move forward system.arraycopy (elements, index + 1, newelements, index, nummoved); <span style= "White-space:pre" ></span>//Set reference SetArray (newelements); } return (E) OldValue;} finally {Lock.unlock ();} }
from the above three methods of updating, adding, deleting, we found that copyonwritearraylist in the process of modifying the original array more than ArrayList do 2 things:
1. Locking: Make sure that when I modify the array, other people cannot modify it.
2. Copy array: No matter which method, it is necessary to copy an array.
The above two things ensure that copyonwritearraylist in the multi-threaded environment can handle freely.
--------------------------------------------------------------------------------------------------------------- -------------------------------------
Iterators:
The Copyonwritearraylist iterator is not a quick failure, that is, the concurrentmodificationexception exception is not thrown . This is because when he modifies it, it is for the copy array and has no effect on the original array. We can see that there is no lock mechanism inside the iterator, so we only provide read, but not add modify and delete (throw unsupportedoperationexcetion).
Public listiterator<e> Listiterator () {return new cowiterator<e> (GetArray (), 0); }private Static class Cowiterator<e> implements Listiterator<e> {//snapshot of original array private final object[ ] Snapshot; subscript private int cursor; Private Cowiterator (object[] elements, int initialcursor) {cursor = Initialcursor; snapshot = elements; } public boolean Hasnext () {return cursor < snapshot.length; } public boolean hasprevious () {return cursor > 0; Public E Next () {if (! Hasnext ()) throw new Nosuchelementexception (); Return (E) snapshot[cursor++]; } public E Previous () {if (! hasprevious ()) throw new Nosuchelementexception (); Return (E) snapshot[--cursor]; } public int Nextindex () {return cursor; } public int Previousindex () {return cursOr-1; }//does not support removing public void remove () {throw new unsupportedoperationexception (); }//does not support modifying public void set (E e) {throw new unsupportedoperationexception (); }//does not support adding public void Add (e e) {throw new unsupportedoperationexception (); } }
copyonwritearraylist deficiency:
Data Consistency issues: If one thread is modifying and the other thread is reading the old data at the moment, that means no data consistency is guaranteed.
Memory Issues:
In the addition, modification, deletion of the operation, will be a large number of copies of the array, when the memory is very small, will produce many new arrays in memory, so that early triggering a series of young GC and full GC, also explained that copyonwritearraylist more suitable for reading, and not suitable with a large number of modifications.
Reference:
Talk about copy-on-write containers in concurrent -java
Look after copyonwritearraylist Source code
Copyright NOTICE: This article is the original blogger articles, reproduced please indicate the source.
Analysis of Copyonwritearraylist source code in-depth collection frame