One: Rapid failure (fail-fast)
When traversing a collection object with an iterator, if the contents of the collection object are modified (added, deleted, modified) during traversal, the concurrent modification Exception is thrown.
Principle: The iterator accesses the contents of the collection directly during traversal, and uses a Modcount variable during traversal. When a collection is traversed, the value of Modcount is changed if the content changes. Each time the iterator uses Hashnext ()/next () to traverse the next element, it detects whether the Modcount variable is a expectedmodcount value, and then returns the traversal, otherwise throws an exception and terminates the traversal.
Note: The exception thrown here is the detection of modcount! =expectedmodcount this condition. The exception is not thrown if the change of the Modcount value is exactly set to the Expectedmodcount value when the collection changes. Therefore, it is not possible to rely on the exception to be thrown and to program concurrent operations, which is only recommended for detecting concurrent modification bugs.
Scenario: The collection class under the Java.util package is fast-failing and cannot be modified in parallel under multiple threads (iterative process).
II: Security Failure (fail-safe)
A collection container using the security failure mechanism, which is not accessed directly on the collection content, but first copies the original collection content and iterates over the copied collection.
Principle: Since iteration is a copy of the original collection, so the changes made to the original collection during traversal cannot be detected by iterators, so concurrent modification Exception is not triggered.
Cons: The advantage of copy-based content is to avoid concurrent modification Exception, but again, iterators do not have access to the modified content, i.e., the iterator iterates through the collection copies that were taken at the moment of the traversal, The modification iterator that occurs during the traversal of the original collection is not known.
Scenario: The container under the Java.util.concurrent package is a security failure that can be used concurrently in multiple threads and concurrently modified.
Another blog post:
Before we discuss the differences between the two mechanisms in detail, we first need to understand the concurrency changes.
1. What is sync modification?
When one or more threads are traversing a collection collection, another thread modifies the contents of the collection (add, delete, or modify). This is the concurrent modification
2. What is the fail-fast mechanism?
The fail-fast mechanism, when traversing a set, throws concurrent modification Exception when the collection structure is modified.
Fail-fast will be thrown in the following two cases concurrentmodificationexception
(1) Single thread environment
After the collection has been created, the structure is modified during the traversal of it.
Note that the Remove () method causes Expectmodcount and modcount to be equal, so this exception is not thrown.
(2) Multi-threaded environment
When a thread is traversing this collection, another thread modifies the structure of the collection.
Note that the fast failure behavior of iterators is not guaranteed because, in general, it is not possible to make any hard guarantees as to whether or not there is a concurrency change in sync. A fast-failing iterator will do its best to throw concurrentmodificationexception. Therefore, it is a mistake to write a program that relies on this exception to improve the correctness of such iterators: The fast failure behavior of iterators should only be used to detect bugs.
3. How is the fail-fast mechanism detected?
Iterators have direct access to internal data during traversal, so the internal data cannot be modified during traversal. To ensure that it is not modified, the iterator internally maintains a tag "mode", when the set structure changes (add delete or modify), the tag "mode" is modified, and the iterator each time the Hasnext () and Next () method will check whether the "mode" is changed, when the detection is modified, Throw Concurrent Modification Exception
Here's a look at the source code for the ArrayList iterator section
Private classItrImplementsIterator<e> { intcursor; intLastret =-1; intExpectedmodcount = ArrayList. This. Modcount; Public BooleanHasnext () {return( This. cursor! = ArrayList. This. Size); } PublicE Next () {checkforcomodification (); /**omit the code here*/ } Public voidRemove () {if( This. Lastret < 0) Throw Newillegalstateexception (); Checkforcomodification (); /**omit the code here*/ } Final voidcheckforcomodification () {if(ArrayList. This. Modcount = = This. Expectedmodcount)return; Throw Newconcurrentmodificationexception (); } }
Can see it's labeled "Mode" for Expectedmodecount
4. Fail-Safe mechanism
Fail-Safe any modifications to the collection structure will be modified on a replicated set, so no concurrentmodificationexception will be thrown
There are two problems with the fail-safe mechanism
(1) The need to replicate the collection, resulting in a large number of invalid objects, overhead
(2) data that is not guaranteed to be read is the data in the current raw data structure.
5 examples of fail-fast and fail-safe
ImportJava.util.HashMap;ImportJava.util.Iterator;ImportJava.util.Map; Public classfailfastexample{ Public Static voidMain (string[] args) {Map<String,String> Premiumphone =NewHashmap<string,string>(); Premiumphone.put ("Apple", "IPhone"); Premiumphone.put ("HTC", "HTC One"); Premiumphone.put ("Samsung", "S5"); Iterator Iterator=Premiumphone.keyset (). iterator (); while(Iterator.hasnext ()) {System.out.println (Premiumphone.get (Iterator.next ())); Premiumphone.put ("Sony", "Xperia Z"); } } }
"Main" java.util.ConcurrentModificationException at java.util.hashmap$hashiterator.nextentry (Unknown SOURCE) at Java.util.hashmap$keyiterator.next (Unknown source) at Failfastexample.main ( Failfastexample.java:20)
ImportJava.util.concurrent.ConcurrentHashMap;ImportJava.util.Iterator; Public classfailsafeexample{ Public Static voidMain (string[] args) {Concurrenthashmap<String,String> Premiumphone =NewConcurrenthashmap<string,string>(); Premiumphone.put ("Apple", "IPhone"); Premiumphone.put ("HTC", "HTC One"); Premiumphone.put ("Samsung", "S5"); Iterator Iterator=Premiumphone.keyset (). iterator (); while(Iterator.hasnext ()) {System.out.println (Premiumphone.get (Iterator.next ())); Premiumphone.put ("Sony", "Xperia Z"); } } }
Output
S5HTC Oneiphone
6. The difference between fail-fast and fail-safe
|
fail Fast Iterator |
Fail Safe Iterator |
Throw concurrentmodification Exception |
Yes |
No |
Clone Object |
No |
Yes |
Memory Overhead |
No |
Yes |
Examples |
Hashmap,vector,arraylist,hashset |
Copyonwritearraylist, Concurrenthashmap |
Interview questions: What is the difference between fast failure (fail-fast) and security failure (fail-safe) in Java?