Java multithreading: CopyOnWrite container, multithreading copyonwrite
1. What is a CopyOnWrite container?
The CopyOnWrite container is the container copied during writing. The general understanding is that when we add elements to a container, instead of directly adding elements to the current container, we first Copy the current container and Copy a new container, add elements to the new container. After adding the elements, point the reference of the original container to the new container. The advantage of doing so is that we can concurrently read the CopyOnWrite container without locking, because the current container does not add any elements. Therefore, the CopyOnWrite container is also an idea of read/write separation. The read and write containers are different.
II. Implementation principle of CopyOnWriteArrayList
Public boolean add (T e) {final ReentrantLock lock = this. lock; lock. lock (); try {Object [] elements = getArray (); int len = elements. length; // copy the new array Object [] newElements = Arrays. copyOf (elements, len + 1); // Add the new element to the new array newElements [len] = e; // point the original array reference to the new array setArray (newElements ); return true;} finally {lock. unlock () ;}} final void setArray (Object [] a) {array = ;}
No lock is required during read. If multiple threads are adding data to the ArrayList during read, The read will still read the old data because the old ArrayList will not be locked during write.
Iii. application scenarios of CopyOnWrite: The CopyOnWrite concurrent container is used for the concurrent scenarios with more reads and less writes. For example, in scenarios such as whitelist, blacklist, and product category access and update, if we have a search website in which users enter keywords in the search box, however, some keywords cannot be searched. These keywords that cannot be searched will be put in a blacklist, which is updated every night. When you search, the system checks that the current keyword is not in the blacklist. If so, the system prompts that the keyword cannot be searched. The code is simple, but you need to pay attention to two things when using CopyOnWriteMap: 1. Reduce the resizing overhead. Initialize the CopyOnWriteMap size as needed to avoid overhead of CopyOnWriteMap resizing during write. 2. Use batch add. Because containers are copied each time they are added, reducing the number of added operations can reduce the number of container copies. For example, use the addBlackList method in the above Code. Iv. disadvantages of CopyOnWrite the CopyOnWrite container has many advantages, but there are also two problems, namely memory usage and data consistency. So pay attention to it during development.
- Memory usage problem: because of the CopyOnWrite write-time replication mechanism, when performing write operations, the memory will be simultaneously stationed in the memory of two objects, the old object and the newly written object (note: during replication, only the reference in the container is copied, but a new object will be created and added to the new container during writing, while the objects in the old container are still in use, so there are two copies of the object memory ). If these objects occupy a large amount of memory, for example, about 300 MB, then MB of data will be written in, and the memory will occupy MB, in this case, frequent Yong GC and Full GC may occur. Previously, we used a service in our system because the CopyOnWrite mechanism was used every night to update large objects, resulting in a Full GC every night for 15 seconds, and the application response time also increased. For memory usage problems, you can reduce the memory consumption of large objects by compressing the elements in the container. For example, if the elements are all decimal numbers, you can consider compressing it into a 36-or 64-digit format. Or use other concurrent containers, such as ConcurrentHashMap, instead of using the CopyOnWrite container.
- Data Consistency: The CopyOnWrite container can only ensure the final consistency of data, but cannot guarantee the real-time consistency of data. Therefore, if you want to read the data you want to write, do not use the CopyOnWrite container.