java concurrent programming Beauty - Reading Record 5

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

 

Guess you like

Origin www.cnblogs.com/nxzblogs/p/11332231.html