java modCount detailed analysis and source code analysis
- 2020-06-03 06:26:56
- OfStack
What exactly does modCount do
In the internal implementation of ArrayList,LinkedList,HashMap and so on, we can always see the figure of modCount, modCount literally means the number of changes, but why record the number of changes of modCount?
There is one common feature that you find out is that all of the modCount attributes are thread-unsafe. Why is that? This must have something to do with thread safety. What does it have to do with thread safety
Reading the source code, I found that this thing is only used in the corresponding iterator of this data structure. Take HashMap as an example:
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; // next entry to return
int expectedModCount; // For fast-fail
int index; // current slot
Entry<K,V> current; // current entry
HashIterator() {
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
}
public final boolean hasNext() {
return next != null;
}
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount;
}
}
As can be seen from the above code, when an iterator is initially given mCount of the object calling the iterator, how can an exception be thrown once the object's mcount is found to be different from the mcount stored in the iterator during the iterator traversal
Ok, here's the full explanation of this
Fail - Fast mechanism
We know that ES34en.util.HashMap is not thread-safe, so if another thread modifies map while using the iterator, it will throw ConcurrentModificationException, which is called the ES39en-ES40en policy. This 1 policy is implemented in the source code through the modCount field. modCount, as the name implies, is the number of changes. Any change to the HashMap content increases this value, which is then assigned to the iterator's expectedModCount during the initializer. During the iteration, determine if modCount is equal to expectedModCount, if not, it means that other threads have already modified Map: note that modCount is declared as volatile to ensure visibility of changes between threads.
It is recommended to use iterators when traversing non-thread-safe data structures
Thank you for reading, I hope to help you, thank you for your support to this site!