Java Concurrency (6): Copy-on-write container in concurrent package

Source: Internet
Author: User

Copy-on-write abbreviation Cow, is a kind of optimization strategy used in program design. The basic idea is that from the beginning everyone is sharing the same content, when someone wants to modify the content, it will really copy the content to form a new content and then change, this is a delay lazy strategy. Starting with JDK1.5 Java Concurrency Package provides two concurrent containers implemented using the Copyonwrite mechanism, which are copyonwritearraylist and Copyonwritearrayset. The Copyonwrite container is very useful and can be used in very many concurrent scenarios.

I. Copyonwrite container

The Copyonwrite container is the container that is copied when it is written. The popular understanding is that when we add elements to a container, instead of adding them directly to the current container, the current container is copied, a new container is duplicated, the new container is added, the element is added, and the reference to the original container is pointed to the new container. The advantage of this is that we can read the Copyonwrite container concurrently, without having to lock it, because the current container does not add any elements. So the Copyonwrite container is also a reading and writing separation of ideas, reading and writing different containers.

Two. Copyonwritearraylist principle of implementation

Before using Copyonwritearraylist, let's read its source code to understand how it is implemented. The following code is to add elements to the ArrayList, you can find that when added is required to lock, or multithreaded writing will be copied out of n copies.

1  Public BooleanAdd (T e) {2     FinalReentrantlock lock = This. Lock;3 Lock.lock ();4     Try {5Object[] elements =GetArray ();6         intLen =elements.length;7         //copy a new array8object[] newelements = arrays.copyof (elements, Len + 1);9         //Add new elements to the new arrayTenNewelements[len] =e; One         //point the original array reference to the new array A SetArray (newelements); -         return true; -}finally { the Lock.unlock (); -     } - } -  + Final voidSetArray (object[] a) { -Array =A; +}

There is no need to lock when reading, if more than one thread is adding data to ArrayList at the time of reading, read or read the old data, because the writing will not lock the old ArrayList.

1  Public E get (int  index) {2     return  get (GetArray (), index); 3 }

The JDK does not provide copyonwritemap, we can refer to Copyonwritearraylist to implement one, the basic code is as follows:

1 Importjava.util.Collection;2 ImportJava.util.Map;3 ImportJava.util.Set;4 5  Public classCopyonwritemap<k, v>ImplementsMap<k, v>, cloneable {6     Private volatileMap<k, v>Internalmap;7 8      PublicCopyonwritemap () {9Internalmap =NewHashmap<k, v>();Ten     } One  A      Publicv put (K key, V value) { -  -         synchronized( This) { theMap<k, v> newmap =NewHashmap<k, v>(INTERNALMAP); -V val =newmap.put (key, value); -Internalmap =Newmap; -             returnVal; +         } -     } +  A      PublicV get (Object key) { at         returnInternalmap.get (key); -     } -  -      Public voidPutall (map<?extendsK?extendsV>NewData) { -         synchronized( This) { -Map<k, v> newmap =NewHashmap<k, v>(INTERNALMAP); in Newmap.putall (newdata); -Internalmap =Newmap; to         } +     } -}

As long as we understand the copyonwrite mechanism, we can implement various copyonwrite containers.

Three. Application scenarios and examples of copyonwrite

Copyonwrite concurrent containers are used for read-write-less concurrency scenarios. such as white list, blacklist, product category to visit and update the scene.

If we have a search site, users in the search box in this site, enter the keyword search content, but some keywords are not allowed to be searched. These keywords that cannot be searched are placed in a blacklist, and the Blacklist is updated every night. When the user searches, it checks that the current keyword is not in the blacklist, and if so, the prompt cannot be searched. The implementation code is as follows:

1  PackageCom.ifeve.book;2 3 ImportJava.util.Map;4 ImportCom.ifeve.book.forkjoin.CopyOnWriteMap;5 6 /**7 * Blacklist service8  */9  Public classBlacklistserviceimpl {Ten  One     Private Staticcopyonwritemap<string, boolean> blacklistmap =NewCopyonwritemap<string, boolean>( A1000); -  -      Public Static Booleanisblacklist (String id) { the         returnBlacklistmap.get (id) = =NULL?false:true; -     } -  -      Public Static voidaddblacklist (String id) { + blacklistmap.put (ID, boolean.true); -     } +     /** A * Batch Add blacklist at      * @paramIDs -      */ -      Public Static voidAddblacklist (map<string,boolean>IDs) { - Blacklistmap.putall (IDS); -     } -  in}

The code is simple, but there are two things to note about using Copyonwritemap:

    1. Reduce the expansion overhead. According to the actual needs, initialize the size of the copyonwritemap to avoid the overhead of copyonwritemap expansion when writing.
    2. Use bulk Add. Because each time it is added, the container replicates every time, so you can reduce the number of times the container replicates by reducing the number of additions. such as using the Addblacklist method in the above code.
Four. Disadvantages of Copyonwrite 1. Memory consumption issues

Because of the copyonwrite of the write-time replication mechanism, so when the write operation, memory will be stationed at the same time the memory of two objects, the old object and the newly written object (note: In the copy is copied only the reference in the container, but at the time of writing will create a new object to add to the new container, The object of the old container is still in use, so there are two copies of the object memory. If these objects occupy a large amount of memory, say 200M or so, then write 100M data in, memory will occupy 300M, then this time is likely to cause frequent Yong GC and full GC. Before we used a service in our system because the copyonwrite mechanism is used to update large objects every night, resulting in a full GC of 15 seconds per night, the application response time also becomes longer.

For memory usage, you can reduce the memory consumption of large objects by compressing the elements in the container, for example, if the elements are all 10 binary numbers, consider compressing them into 36 or 64 binary. Or do not use the Copyonwrite container, but use other concurrent containers, such as Concurrenthashmap.

2. Data consistency issues

The Copyonwrite container can only guarantee the final consistency of the data and cannot guarantee the real-time data consistency. So if you want to write the data that can be read right away, please do not use the Copyonwrite container.

Reference: http://ifeve.com/java-copy-on-write/

Java Concurrency (6): Copy-on-write container in concurrent package

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.