[Reprint] Fail-fast summary (through ArrayList to explain the principle of fail-fast, solutions)

Source: Internet
Author: User
Tags concurrentmodificationexception

Description: Reprinted from http://www.cnblogs.com/skywang12345/p/3308762.html
Overview

In the front, we have learned ArrayList. Next, we take ArrayList as an example to understand the fail-fast mechanism of iterator. The content includes:
1 Fail-fast Introduction
2 Fail-fast Example
3 Fail-fast Solutions
4 Fail-fast Principle
5 How to solve Fail-fast

1 Fail-fast Introduction

The fail-fast mechanism is an error mechanism in the Java Collection (Collection). Fail-fast events can occur when multiple threads operate on the contents of the same collection.
For example, when a thread A is traversing a collection through iterator, if the contents of the collection are changed by another thread, thread a accesses the collection and throws an Concurrentmodificationexception exception, resulting in a fail-fast event.

Before detailing the principles of the fail-fast mechanism, let's first recognize fail-fast with an example.

2 Fail-fast Example

Example code: (Fastfailtest.java)

View Code

Operation result :
Run the code, throw an exception java.util.concurrentmodificationexception! That is, generate Fail-fast events!

Result Description :
(in Fastfailtest), start () and new Threadtwo () starting () started with new Threadone (). Starts () Two threads to operate the list.
Threadone thread : Adds a 0,1,2,3,4,5 to the list in turn. After each number is added, the entire list is traversed through printall ().
threadtwo thread : Adds a 10,11,12,13,14,15 to the list in turn. After each number is added, the entire list is traversed through printall ().
(02) When a thread iterates through the list, the contents of the list are changed by another thread, and the concurrentmodificationexception exception is thrown and the Fail-fast event is generated.

3 Fail-fast Solutions

Fail-fast mechanism is a kind of error detection mechanism. It can only be used to detect errors because the JDK does not guarantee that the fail-fast mechanism will happen. If you are using a collection of fail-fast mechanisms in a multithreaded environment, it is recommended to replace the class under the Java.util package with the class under the Java.util.concurrent package.
So, in this case, you just need to replace the ArrayList with the corresponding class under the Java.util.concurrent package.
That is, the code

private static list<string> List = new arraylist<string> ();

Replaced by

private static list<string> List = new copyonwritearraylist<string> ();

You can resolve this approach.

4 fail-fast Principle

The Fail-fast event is generated by throwing a concurrentmodificationexception exception to trigger.
So, how does ArrayList throw concurrentmodificationexception exceptions?

We know that Concurrentmodificationexception is the exception that is thrown when you manipulate iterator. Let's look at the source code of iterator first. The iterator of ArrayList is implemented in the parent class Abstractlist.java. The code is as follows:

View Code

From there, we can see that the checkforcomodification () is executed when you call next () and remove (). If "modcount is not equal to Expectedmodcount", the concurrentmodificationexception exception is thrown, resulting in a fail-fast event.

To understand fail-fast mechanism, we need to understand when "modcount is not equal to Expectedmodcount"!
From the ITR class, we know that Expectedmodcount is assigned a value of Modcount when creating ITR objects. Through ITR, we know: Expectedmodcount cannot be modified to be not equal to Modcount. Therefore, it is necessary to verify when Modcount will be modified.

Next, we look at the source code of ArrayList, to see how Modcount was modified.

View Code

From this, we find that either add (), remove (), or clear () changes the value of Modcount as long as it involves modifying the number of elements in the collection.

Next, we will systematically comb how the fail-fast is produced. The steps are as follows:
A new ArrayList is created with the name ArrayList.
add content to ArrayList.
(03) Create a new thread a, and read the ArrayList value repeatedly through iterator in thread A.
Create a new thread Band remove a "Node a" in ArrayList in thread B.
(05) At this point, an interesting event is produced.
At some point, "thread A" created the ArrayList iterator. At this point, "Node A" still exists in ArrayList, when creating arraylist, Expectedmodcount = Modcount(assuming they have a value of n at this time).
"Thread A" was executed at some point during the traversal of the ArrayList process, and thread B removed "Node A" in ArrayList. When thread B executes remove (), "modcount++" is executed in remove (), and Modcount becomes n+1!
"Thread A" then traverses, when it executes to the next () function, calls Checkforcomodification () to compare the size of "Expectedmodcount" and "Modcount", while "expectedmodcount=n", " Modcount=n+1 ", so that the concurrentmodificationexception exception is thrown and the Fail-fast event is generated.

At this point, we fully understand how fail-fast is produced!
That is, when multiple threads operate on the same set, when a thread accesses the collection, the contents of the collection are changed by other threads (that is, other threads change the value of the Modcount by means of Add, remove, clear, etc.); The concurrentmodificationexception exception is thrown and the Fail-fast event is generated.

5 How to solve Fail-fast

Above, explained the "solution fail-fast mechanism", also knew "fail-fast the root cause". Next, let's talk a little further about how the Java.util.concurrent package solves the Fail-fast event.
or ArrayList corresponding to the copyonwritearraylist to explain. Let's take a look at Copyonwritearraylist's source code:

1  Packagejava.util.concurrent;2 ImportJava.util.*;3 Importjava.util.concurrent.locks.*;4 ImportSun.misc.Unsafe;5 6  Public classCopyonwritearraylist<e>7     ImplementsList<e>, Randomaccess, cloneable, java.io.Serializable {8 9     ...Ten  One     //returns the iterator for the collection A      PublicIterator<e>iterator () { -         return NewCowiterator<e> (GetArray (), 0); -     } the  -     ... -     -     Private Static classCowiterator<e>ImplementsListiterator<e> { +         Private Finalobject[] Snapshot; -  +         Private intcursor; A  at         PrivateCowiterator (object[] elements,intinitialcursor) { -cursor =Initialcursor; -             //When you create a new cowiterator, the elements in the collection are saved to a new copy array.  -             //Thus, when the data of the original collection changes, the values in the copied data do not change.  -snapshot =elements; -         } in  -          Public BooleanHasnext () { to             returnCursor <snapshot.length; +         } -  the          Public Booleanhasprevious () { *             returnCursor > 0; $         }Panax Notoginseng  -          PublicE Next () { the             if(!Hasnext ()) +                 Throw Newnosuchelementexception (); A             return(E) snapshot[cursor++]; the         } +  -          PublicE Previous () { $             if(!hasprevious ()) $                 Throw Newnosuchelementexception (); -             return(E) snapshot[--cursor]; -         } the  -          Public intNextindex () {Wuyi             returncursor; the         } -  Wu          Public intPreviousindex () { -             returnCursor-1; About         } $  -          Public voidRemove () { -             Throw Newunsupportedoperationexception (); -         } A  +          Public voidset (e e) { the             Throw Newunsupportedoperationexception (); -         } $  the          Public voidAdd (e e) { the             Throw Newunsupportedoperationexception (); the         } the     } -    in     ... the  the}
View Code

From this, we can see:

(01) and ArrayList inherit from Abstractlist, Copyonwritearraylist does not inherit from Abstractlist, it simply implements the list interface.
The iterator returned by the iterator () function of ArrayList is implemented in Abstractlist, and Copyonwritearraylist is its own implementation iterator.
When next () is called in the iterator implementation class of ArrayList, "Checkforcomodification () is called to compare the size of ' expectedmodcount ' and ' modcount '; Copyonwritearraylist iterator implementation class, there is no so-called checkforcomodification (), and will not throw a Concurrentmodificationexception exception!

[Reprint] Fail-fast summary (through ArrayList to explain the principle of fail-fast, solutions)

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.