java and contracting in the concurrent List
5.1CopeOnWriteArrayList
And contracting in the concurrent List only CopyOnWriteArrayList, this class is a thread-safe arraylist, modify its operations are carried out on a copy of the underlying array, which is used to write when replication strategy.
Class structure:
public class a CopyOnWriteArrayList <E> the implements List <E> , the RandomAccess, the Cloneable, the java.io.Serializable { Private static Final Long serialVersionUID = 8673264195747942595L ; // reentrant exclusive lock, to ensure arraylist modification operations on the same time only one thread Final transient of ReentrantLock = Lock new new of ReentrantLock (); // store object underlying array visibility of memory Private transient volatile object [] array; // hardware-based atomic instructions the Unsafe Private static Final sun.misc.Unsafe the UNSAFE; // lock offset private static final long lockOffset; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> k = CopyOnWriteArrayList.class; lockOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("lock")); } catch (Exception e) { throw new Error(e); } } }
problem:
When initialization list, initialization list size is the number, list size is limited right? copyonwriteArraylist is unbounded array
How to ensure the security thread, such as how to ensure that when multiple threads read and write thread-safe?
How to ensure data consistency when iterates over list?
5.2 source code analysis
1, initialization
Constructor:
// empty list public a CopyOnWriteArrayList () { setArray ( new new Object [0 ]); } // set the parameters for the type of Collection, will copy the configuration set list of elements to the public ? A CopyOnWriteArrayList (Collection < the extends E > C) { Object [] Elements; IF . (c.getClass () == a CopyOnWriteArrayList class ) Elements = (? (a CopyOnWriteArrayList <> ) C) .getArray (); the else { Elements = c.toArray (); // Might c.toArray (incorrectly) Not return Object [] (See 6,260,652) IF(elements.getClass () = Object []!. class ) Elements = Arrays.copyOf (Elements, elements.length, Object []. class ); } setArray (Elements); } // parameter into a generic array, copies the array to the bottom of the array list public a CopyOnWriteArrayList (E [] toCopyIn) { setArray (Arrays.copyOf (toCopyIn, toCopyIn.length, Object []. class )); }
2, add the additive element method
// add elements, added at the end of the list public Boolean the Add (E E) { Final of ReentrantLock = Lock the this .lock;
// exclusive lock Lock.lock (); the try {
// Get copyOnWriteArrayList underlying array Object [] Elements = getArray (); int len = elements.length;
// copy of the new array, the array than the original first year, it is a CopyOnWriteArraylist unbounded array Object [] the newElements = Arrays.copyOf (Elements, len +. 1 );
// elements to be added into the final location of the new array the newElements [len] = E;
// replace the original array with the new array setArray (the newElements); return to true ; } the finally {
// After the operation is completed, release the exclusive lock lock.unlock (); } }
3, obtaining the elements, then it will generate a weak replication write consistency: when a thread formation to obtain an array, but not execute get (Object [] a, int index) method, then the set operation thread b delete an element (deleted data is duplicated in the new array, but will use the new array covering the old array), name a thread continues to acquire data execution position, in which case the underlying array is still not deleted before the data array , thus creating a weak consistency problem.
// direct access to the underlying array data specified index Private E GET (Object [] A, int index) { return (E) A [index]; } // Get the specified index value of the underlying array getArray method returns public E GET ( int index) { return GET (getArray (), index); }
4, to modify the position of the specified element
public E SET ( int index, E Element) { Final of ReentrantLock = Lock the this .lock; // exclusive lock Lock.lock (); the try { // Get the underlying array Object [] = Elements getArray (); // the index to obtain the modified value E oldValue = gET (Elements, index); // if the new value is not equal to the old value, it will copy the array, enter the new value set, then covered it with a new array of arrays IF (oldValue! = Element) { int len = elements.length; Object [] the newElements =Arrays.copyOf (Elements, len); the newElements [index] = Element; setArray (the newElements); } the else { // Not quite A NO-OP; Write Ensures volatile semantics // old array to re-cover the old array -> This step Although no change in the array, but in order to ensure volatitle semantics, still resets once setArray (Elements); } return oldValue; } the finally { // release lock lock.unlock (); } }
5, remove elements
public E Remove ( int index) { Final of ReentrantLock = Lock the this .lock; Lock.lock (); the try { Object [] Elements = getArray (); int len = elements.length; // Get index position to remove the element E = oldValue GET (elements, index); // calculate the number of elements to be moved int numMoved = len - index -. 1 ; // element to move is 0, represents the last element is deleted IF (numMoved == 0 ) setArray (Arrays.copyOf (Elements, len - 1)); The else { // to be deleted is not the last one, a new array of length len-1 Object [] = the newElements new new Object [len -. 1 ]; // while the indexes index to be deleted as the boundary, copy 0-index, index + 1 - len elements System.arraycopy (elements, 0, the newElements, 0 , index); System.arraycopy (elements, index +. 1 , the newElements, index, numMoved); setArray (the newElements); } return oldValue; } the finally { lock.unlock (); } }
6, weakly consistent iterator
The so-called weak consistency means: After returning iterator, other threads of the list of operations (additions and deletions) to the iterator is not visible.
public the Iterator <E> Iterator () { return new new COWIterator <E> (getArray (), 0 ); } // see methods iterator, additions and deletions not, the corresponding method throws exception static Final class COWIterator <E> the implements the ListIterator <E> { / ** the Snapshot of The Array * / Private Final Object [] Snapshot; / ** Index of Element by Subsequent to BE returned to Call Next. * / 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; } @SuppressWarnings("unchecked") public E next() { if (! hasNext()) throw new NoSuchElementException(); return (E) snapshot[cursor++]; } @SuppressWarnings("unchecked") public E previous() { if (! hasPrevious()) throw new NoSuchElementException(); return (E) snapshot[--cursor]; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor-1; } public void remove() { throw new UnsupportedOperationException(); } public void set(E e) { throw new UnsupportedOperationException(); } public void add(E e) { throw new UnsupportedOperationException(); } @Override public void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); Object[] elements = snapshot; final int size = elements.length; for (int i = cursor; i < size; i++) { @SuppressWarnings("unchecked") E e = (E) elements[i]; action.accept(e); } cursor = size; } }
Weak Consistency:
Package com.nxz.blog.otherTest; Import the java.util.Iterator; Import java.util.concurrent.CopyOnWriteArrayList; public class TestThread003 { Private static CopyOnWriteArrayList <String> = CopyOnWriteArrayList new new CopyOnWriteArrayList <> (); / ** * Test CopyOnWriteArrayList weak consistency * If the output is: test1 test2 test3 test4 then the class having weak consistency
* / public static void main (String [] args) throws InterruptedException { copyOnWriteArrayList.add ( "test1" ); copyOnWriteArrayList.add ( "test2" ); copyOnWriteArrayList.add("test3"); copyOnWriteArrayList.add("test4"); Thread t = new Thread(new Runnable() { @Override public void run() { copyOnWriteArrayList.add("runnabl1"); copyOnWriteArrayList.add("runnabl2"); copyOnWriteArrayList.add("runnabl3"); } }); Iterator<String> iterator = copyOnWriteArrayList.iterator(); waiting thread is finished// t.join (); the while (iterator.hasNext ()) { System.out.println (Iterator.next ()); } } }
The results:
test1
test2
Test3
Test4