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)