1. ホーム
  2. ジャワ

Javaコレクションで一般的なcheckForComodification()メソッドは何をするのですか?modCount と expectedModCount の役割?

2022-02-25 08:13:30
<パス

主にフェイルファスト機構を実装するために使用されます

<ブロッククオート

2つのスレッド(スレッドA、スレッドB)があり、スレッドAはリストのトラバースを担当し、スレッドBはリストを修正します。
-スレッドAは、リストを巡回している途中のある時点(expectedModCount = modCount=Nのとき)から開始され
同時にスレッドBが要素を追加し、modCountの値が変化する(modCount + 1 = N + 1)。スレッド A が次の実行方法を反復し続けるので
通知されたcheckForComodificationメソッドは、expectedModCount = N 、およびmodCount = N + 1、これらは等しくないことを発見します。
これは ConcurrentModificationException 例外を投げるので、結果的にフェイルファスト機構となる。

/**
 * Currently fetching code from JDK1.8 ArrayList
 */

/**
 * The number of times this list has been <i>structurally modified</i>.
 * Structural modifications are those that change the size of the
 structural modifications are those that change the size of the * list, or otherwise perturb it in such a fashion that iterations in
 Structural modifications are those that change the size of the * list, or otherwise perturb it in such a fashion that iterations in * progress may yield incorrect results.
 *
 * <p>This field is used by the iterator and list iterator implementation
 * returned by the {@code iterator} and {@code listIterator} methods.
 * If the value of this field changes unexpectedly, the iterator (or list
 * If the value of this field changes unexpectedly, the iterator (or list iterator) will throw a {@code ConcurrentModificationException} in
 * response to the {@code next}, {@code remove}, {@code previous},
 * This provides
 * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
 * the face of concurrent modification during iteration.
 *
 * <p><b> Use of this field by subclasses is optional.</b> If a subclass
 * If a subclass wishes to provide fail-fast iterators (and list iterators), then it
 * merely has to increment this field in its {@code add(int, E)} and
 * {@code remove(int)} methods (and any other methods that it overrides
 * that result in structural modifications to the list).  A single call to
 * {@code add(int, E)} or {@code remove(int)} must add no more than
 * one to this field, or the iterators (and list iterators) will throw
 * bogus {@code ConcurrentModificationExceptions}.  If an implementation
 If an implementation * does not wish to provide fail-fast iterators, this field may be
 If an implementation * does not wish to provide fail-fast iterators, this field may be * ignored.
 */If an implementation * does not wish to provide fail-fast iterators, this field may be * ignored.
protected transient int modCount = 0;

親クラスAbstractListにint型プロパティが定義されています: modCount

protected transient int modCount = 0;

add(), remove(), addAll(), removeRange(), clear() メソッドを含む、構造の変更を伴う ArrayList のすべてのメソッドに modCount の値を追加します。これらのメソッドが呼ばれるたびに、modCountの値が1ずつ加算されます。

Note: The value of modCount for the add() and addAll() methods is added in the ensureCapacity() method called there.



AbstractList(ArrayListを直接継承)のiterator()メソッドは、内部のプライベートメンバークラスItrを使用して、Itrオブジェクト(Iteratorインターフェース)を返すように生成しています。

public Iterator iterator() { return new Itr(); }

ItrはIterator()インターフェースを実装しており、int型プロパティとしてexpectedModCountを定義しています。このプロパティはItrクラスの初期化時にArrayListオブジェクトのmodCountプロパティの値として与えられます。

int expectedModCount = modCount;
Note: The internal member class Itr is also a member of the ArrayList class, and it has access to all the properties and methods of the AbstractList. Understanding this makes the implementation of the Itr class easy to understand.

public boolean hasNext() { return cursor ! = size; }

Itr.hasNext()メソッド内。

public Object next()  
{  
 try  
 {  
  Object next = get(cursor);  
  checkForComodification();  
  lastRet = cursor++;  
  return next;  
 }  
 catch(IndexOutOfBoundsException e)  
 {  
  checkForComodification();  
  throw new NoSuchElementException();  
 }  
}  
/**
* While performing a drop generation operation on a collection object, there is no restriction on operating on the elements of the collection object
* These operations include some dangerous operations such as add() or remove() that can cause drop generation errors.
* In AbstractList, a simple mechanism is used to circumvent these risks. 
* This is where modCount and expectedModCount come into play
*/
final void checkForComodification() {
   if (modCount ! = expectedModCount)
        throw new ConcurrentModificationException();
}

AbstractListのサイズが呼び出され、現在のカーソル位置が範囲外であるかどうかが比較されます。

public Object next()  
{  
 try  
 {  
  Object next = get(cursor);  
  checkForComodification();  
  lastRet = cursor++;  
  return next;  
 }  
 catch(IndexOutOfBoundsException e)  
 {  
  checkForComodification();  
  throw new NoSuchElementException();  
 }  
}  
/**
* While performing a drop generation operation on a collection object, there is no restriction on operating on the elements of the collection object
* These operations include some dangerous operations such as add() or remove() that can cause drop generation errors.
* In AbstractList, a simple mechanism is used to circumvent these risks. 
* This is where modCount and expectedModCount come into play
*/
final void checkForComodification() {
   if (modCount ! = expectedModCount)
        throw new ConcurrentModificationException();
}