1.Copy-On-WriteWhat is?

First of all, let me show you what copy-on-write is, and what it means in a computer is when you want to change a piece of memory, instead of writing to the old block, we Copy the memory, we Write to the new memory, and when we’re done, we point to the old memory and we point to the new memory, The original memory can be recycled!

Online brothers say that this is an optimization strategy used in programming, is a lazy strategy of delay. All say optimization optimization, so what problems are optimized?

Let me give you a code:

public class IteratorTest {

	private static List<String> list = new ArrayList<>();

	public static void main(String[] args) {
		
		list.add("1");
		list.add("2");
		list.add("3"); Iterator<String> iter = list.iterator(); // I am currently iterating over the collection (this is to simulate a concurrent reading of a list)while(iter.hasNext()) { System.err.println(iter.next()); } System.err.println(Arrays.toString(list.toArray())); }}Copy the code

The above program snippet in a single threaded execution is fine, but in a multi-threaded environment, it may be GG! Why is that? Because a multithreaded environment, you are in the iteration is not allowed to have other threads to add elements of the set list, look at the code below, you will find that throw Java. Util. ConcurrentModificationException abnormalities.

public class IteratorTest {

	private static List<String> list = new ArrayList<>();

	public static void main(String[] args) {

		list.add("1");
		list.add("2");
		list.add("3"); Iterator<String> iter = list.iterator(); / / store 10 threads thread pool ExecutorService service = Executors. NewFixedThreadPool (10); // Execute 10 tasks (I'm currently iterating over the collection (here simulates a concurrent reading of a list))for (int i = 0; i < 10; i++) {
			service.execute(new Runnable() {
				@Override
				public void run() {
					while(iter.hasNext()) { System.err.println(iter.next()); }}}); } // Execute 10 tasksfor (int i = 0; i < 10; i++) {
			service.execute(new Runnable() {
				@Override
				public void run() {
					list.add("121"); // Add data}}); } System.err.println(Arrays.toString(list.toArray())); }}Copy the code
  • 1. HereThe iterationThat means I’m currently reading somethingA collection of, belongs toreadOperation;
  • 2, the thread simulates the current program in a multi-threaded environment, there are other threads are modifying the data

What’s the problem here?

  • 1. Multithreading affects the iteration set, affecting read operations

Solution:

  • 1.CopyOnWriteArrayListAvoid multithreaded operation List thread is not safe

2,CopyOnWriteArrayListintroduce

There are two concurrent containers that use CopyOnWrite. They are CopyOnWriteArrayList and CopyOnWriteArraySet. The CopyOnWrite container is very useful and can be used in a wide range of concurrent scenarios.

CopyOnWriteArrayList principle:

As I said, you don't change the set when you write it, you make a new copy, and then you move the pointerCopy the code

So you might ask? Wouldn’t copying even the original set cause write collisions in a multi-threaded environment? That’s true, but if you don’t know the details of how CopyOnWriteArrayList adds and deletes elements, let’s talk about the add() method that’s often mentioned on the Web

3,CopyOnWriteArrayListSimple source code interpretation

Add () method source

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})*/ public boolean add(E e) { final ReentrantLock lock = this.lock; // Reentrant lock lock.lock(); Try {Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); NewElements [len] = e;setArray(newElements); // Make the reference to the new array 1return true; } finally { lock.unlock(); }}Copy the code

Add () locks the collection when it is added, ensuring synchronization and avoiding the need for multiple threads to Copy N copies. (Think about it, you’re walking through a set of 10 elements, and each time one person calls the add method, you say, when you walk 10 times, does the add method have to be called 10 times? Do you have to copy a new set of 10 points? What if the set is really big?)

So? You still ask? How does CopyOnWriteArrayList solve thread-safety issues? The answer is —- copy on write, lock and ask? Is there a case where a thread just finished calling the add() method, which is exactly the same as the code at 1 above, which is exactly the reference to the core array, and a thread is walking through it? Will there be an error? (The answer is no, because the set you’re traversing is old, which makes it a little uncomfortable.)

When you change the ArrayList of the above code to CopyOnWriteArrayList, the execution will not report errors!

public class IteratorTest {

	private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

	public static void main(String[] args) {

		list.add("1");
		list.add("2");
		list.add("3"); Iterator<String> iter = list.iterator(); / / store 10 threads thread pool ExecutorService service = Executors. NewFixedThreadPool (10); // Execute 10 tasks (I'm currently iterating over the collection (here simulates a concurrent reading of a list))for (int i = 0; i < 10; i++) {
			service.execute(new Runnable() {
				@Override
				public void run() {
					while(iter.hasNext()) { System.err.println(iter.next()); }}}); service.execute(newRunnable() {
				@Override
				public void run() {
					list.add("121"); // Add data}}); } // Execute 10 tasksfor (int i = 0; i < 10; i++) {
			service.execute(new Runnable() {
				@Override
				public void run() {
					list.add("121"); // Add data}}); service.execute(newRunnable() {
				@Override
				public void run() {
					while(iter.hasNext()) { System.err.println(iter.next()); }}}); } System.err.println(Arrays.toString(list.toArray())); }}Copy the code

4,CopyOnWriteArrayListThe advantages and disadvantages

Disadvantages:

  • 1. Memory consumption (collection replication)
  • 2. Low real-time performance

Advantages:

  • 1. Complete data consistency. Why? Because of the lock, the concurrent data will not mess
  • 2, SolvedLike ArrayList,VectorThis collection multi-threaded iterating problem, remember,VectorAlthough thread-safe, it just addssynchronizedKeyword, the iteration problem is not solved at all!

5,CopyOnWriteArrayListUsage scenarios

  • 1, read more than write (whitelist, blacklist, commodity access and update scenarios), why? Because when you write it, you copy the new set
  • 2, the collection is not large, why? Because when you write it, you copy the new set
  • The real time requirement is not high, why, because it is possible to read the old collection data

Reference article: How to thread safely traverse List: Vector, CopyOnWriteArrayList


Xiaobian senior, internship, knowledge is still shallow, welcome to comment exchange, study together, progress together!