質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Java

    16753questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

並列コレクションの問題を理解したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 855

k499778

score 521

現在Java Goldの問題を解いています。
その中で並列コレクションの問題を解いているのですが、理解できない箇所があるためアドバイス頂けたらと思い質問しました。

問題は以下で、実行結果は「実行時エラー(java.util.ConcurrentModificationException)が発生する」というものです。

import java.util.*;

class Test {
  public static void main(String[] args) {
    Set<String> set = new TreeSet<String>();
    set.add("A"); set.add("B");
    Iterator<String> ite = set.iterator();
    set.add("C"); set.add("D");
    while(ite.hasNext()){
      System.out.print(ite.next() + " ");
    }
  }
}

しっくりこないところは
結論から言うと、
なぜ直接イテレータオブジェクトに詰めている訳ではないのに、
ite.next()の部分で実行時エラーが発生してしまうのかということです。

イテレータオブジェクト生成後、TreeSetオブジェクトに要素を追加し、要素の取り出しを行っているためエラーが発生する。ということはわかりました。

しかし、文字列C,Dは直接イテレータオブジェクトに詰め込んでいないし、
要素を取り出そうとしているのはsetとかでなく、イテレータオブジェクトに対してなのでなぜ影響が出るのかわかりません。そこがしっくりきていない箇所です。

ConcurrentModificationException例外は「あるスレッドがコレクションで繰り返し処理を行っている間に、別のスレッドがそのコレクションを変更する」といったときに起こるという認識ですが、
スレッドもコードに特に記述がないので、なぜ起きているのかわかっていません。

Set<String> set = new TreeSet<String>(); を
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<String>(); に変えるとスレッドセーフとなるため例外が発生しないことも知っています。C,D追加の変更は反映されませんが。

言葉ではわかっているけどロジック的に理解できていないような感じです。
アドバイスいただけると幸いです。よろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

イテレータオブジェクトは元になったオブジェクトのことを見ています。
具体的には「あのオブジェクトの、バージョン○○のときの○番目まで取り出した」という情報を格納しています。

元オブジェクトに改変が加わった時点で元オブジェクトは自身のバージョン番号を上げる(このバージョン番号という数値はパッケージローカールなので利用者からはアクセスできないものです)ので、イテレータは値を取り出そうとして「バージョン番号が違うじゃん!」と怒って例外を投げる、そんな仕組みです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/03 12:47

    お!

    TreeMapクラスのKeyIteratorインナークラスがPrivateEntryIterator<K>抽象クラスを継承し、


    final class KeyIterator extends PrivateEntryIterator<K> {
    KeyIterator(Entry<K,V> first) {
    super(first);
    }
    public K next() {
    return nextEntry().key;
    }
    }


    PrivateEntryIterator<K>抽象クラスがIterator<T>インターフェイスを実装していました。
    abstract class PrivateEntryIterator<T> implements Iterator<T> {
    Entry<K,V> next;
    Entry<K,V> lastReturned;
    int expectedModCount;


    そのためオーバーライドしたKeyIteratorクラスのnext()の処理が走っていた訳ですね。
    微々たる知識ながら流れを理解したつもりです。

    swordoneさん、アドバイスいただきありがとうございます。

    キャンセル

  • 2017/05/03 15:30

    解決してよかったです。
    あとソースを読んでいないのではと勝手に決めつけた非礼はお詫びさせてください。

    キャンセル

  • 2017/05/03 22:46

    yubaさん
    ありがとうございました。yubaさんのおかげでスッキリ解決することができました。
    いえ全く問題ないです😊
    ありがとうございました。

    キャンセル

+1

ConcurrentModificationException例外は「あるスレッドがコレクションで繰り返し処理を行っている間に、別のスレッドがそのコレクションを変更する」といったときに起こるという認識ですが、 

この例外に関する質問はいくつかあり、よく誤解されていますが、この例外のドキュメントを見に行くと、

たとえば、あるスレッドがCollectionで反復処理を行っている間に、別のスレッドがそのCollectionを変更することは一般に許可されません。

とある通り、あくまで一例なのです。
例えるなら、エクセルで作った表をファックスで送るという場合(メールで送れよという突っ込みはなしで)、送るために読み込んでいる最中に「ちょっとここの行追加で」みたいなことやられると、ファックス側が「ちょ、ちょっと待って」となるわけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/03 12:28

    回答ありがとうございます。すごくわかりやすいです!笑
    そういったときに起こる例外が「ConcurrentModificationException例外」なのですね!
    大変参考になりました。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    16753questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。