2016-06-25 13 views
1

私は楽しいために書いていた様々なプログラムで、同時の変更例外を遭遇しました。AtomicReference <ArrayList>難易度と代替方法

この問題を解決しようと私の素朴な試みで、私は何らかの並行コレクションのAtomicinsteadを使用しました。私はなぜこれがケーシングエラーであるのか、なんとなく分かりました。基本的には、ArrayListの個々の要素は同期されておらず、別のスレッドによって変更することができます。


誰かが私のために要約でした私は、配列またはリスト 原子の参照のための合法的なユースケースでどのようなコレクション
  • に、原子の参照を作成しようとするとエラーが発生する何

  • 複数のスレッドで使用できるゲームのためのインスタンスを格納するためのいくつかのより良い代替手段はどのようなものがあり

  • +0

    "コレクションのコレクションに"?どういう意味ですか? –

    答えて

    2
    私はあなたがConcurrentModificationが何を意味するのか混乱していると思う

    ...

    このための最も一般的な発生があります。例えば

    public static void main(String[] args) { 
         List<String> l = new LinkedList<>(); 
         for(int i=0; i < 100; i++) { 
          l.add("banana"+i); 
         } 
    
         for (String s : l) { 
          if("banana10".equals(s)) { 
           l.remove(s); 
          } 
         } 
        } 
    

    をすれば...これはあなたにConcurrentModificationExceptionを与えるだろう。注意してください、私はスレッドを生成していません。

    次のように同じことを行うための正しい方法は次のとおりです。

    public static void main(String[] args) { 
        List<String> l = new LinkedList<>(); 
        for(int i=0; i < 100; i++) { 
         l.add("banana"+i); 
        } 
    
        for (Iterator<String> iterator = l.iterator(); iterator.hasNext();) { 
         String s = iterator.next(); 
         if("banana10".equals(s)) { 
          iterator.remove(); 
         } 
        } 
    } 
    

    あなたはそれをループしている間、コレクションを変更するイテレータの使用に注意してください。

    私はあなたに並行性の問題はないと思います!

    コレクションをスレッドセーフにしたい場合は、スレッドの安全性のセマンティクスを調べる必要があります。複数のスレッドが同じコレクションにアクセスできるようにする場合は、ConcurrentListを使用するとよいでしょう。原子的に設定されたリスト参照が必要な場合は、全体としてAtomic参照を使用できます。

    +0

    防御的なコピーソリューションを追加することをお勧めします –

    +0

    ConcurrentList?どこの図書館からですか? –

    +0

    Collections.synchronizedList()を使用してリストを安全にするか、Vectorを使用するかのいずれかを行うことができます。 –

    1

    AtomicReferenceを使用してコレクションなどのオブジェクトを格納するだけでは、スレッドを安全にするには不十分です。実際にAtomicReferenceに入れたオブジェクトがArrayListのようなスレッドセーフではない場合、複数のスレッドが同時に状態を変更しようとすると、それを使用しても安全ではありません。ですから、良い方法は、依然としてあなたのAtomicReferenceに状態を変更することができないような不変のオブジェクトを複数のスレッドで入れ替えることです。コレクションの場合は、例えばCollections.unmodifiableList(List)のようなタイプCollections.unmodifiable*のメソッドをリストに使用して、コレクションの不変バージョンAtomicReferenceを入れることができます。

    スレッドセーフなコレクションが必要な場合は、パッケージjava.util.concurrentのクラスを参照すると、ネイティブスレッドセーフであるコレクションが見つかります。たとえば、ほとんどあなたがListを読んで稀にしか変更しない場合は、スレッドセーフで効率的なリストCopyOnWriteArrayListを使用することができます。あなたは、コレクションを反復処理し、ループの中でそれを変更するとき

    +0

    'Collections.unmodifiableList(List)'によって生成されるリストは不変ではありません。ラップされたリストは変更される可能性があります。真に不変なリストの場合は、例えばguavaの 'ImmutableList'を使用します。 –