1

同じオブジェクト、たとえば MyObject を変更する 2 つのスレッドがあり、オブジェクトを同期しました。しかし、スレッドの 1 つで別のオブジェクトが変更されているため、MyObject を呼び出す必要があります。

いえ

public void run(){
   synchronized(MyObject){
             ...
            anotherObject.modify();//<----calls MyObject
             ...
    }
 }

これにより、ConcurrentModificationExceptions が発生しています。これを解決する方法がわかりません。同期しないと、両方のスレッドが MyObject を呼び出そうとするため、例外が発生します。どうすればこれを修正できますか?

更新: コードは Android デバイス用です。ここでは Android 固有のオブジェクトが使用されていないため、これまで言及していませんでした。LogCat の出力はあまり役に立ちません

02-03 02:47:43.660: エラー/AndroidRuntime(5258): キャッチされていないハンドラー: キャッチされていない例外が原因で終了するスレッドのメイン 02-03 02:47:43.670: エラー/AndroidRuntime(5258): java.util.ConcurrentModificationException 02-03 02:47:43.670: エラー/AndroidRuntime(5258): java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64) 02-03 02:47:43.670: エラー/AndroidRuntime(5258): com.jjg .myapp.gameunit.findEnemy(MoveableUnit.java:656)//<--- このメソッドでは、Gamestate のコレクションは 02-03 02:47:43.670: ERROR/AndroidRuntime(5258): at com.jjg.myapp. gameunit.update(GameUnit.java:416)

同期しようとしていたオブジェクトは、基本的に gs と呼ばれる GameState です。ArrayLists、配列、およびその他のオブジェクトの品揃えを収容します。gs は静的ではありません。

問題が発生する上記の方法は次のとおりです。

for(GameUnit gu : this.getBase().getGameState().getAllUnits()){//<---this is the problem line.
//do some stuff...
 }

getAllUnits は、GameUnits の ArrayList を返します (メソッドを呼び出す GameUnit を含む - オブジェクトが削除または作成されないため、反復子は必要ありません)。

4

4 に答える 4

1

ConcurrentModificationExceptionイテレータを使用しているときにコレクションが変更されると、Aがスローされることがよくあります。-- つまり、あなたは名前に惑わされて、間違った問題を検索するだけです。

于 2012-02-02T18:13:52.073 に答える
1

あなたは本当にこれと同じ質問をしています:コレクションに対するスレッドセーフな反復

最も簡単な解決策は、反復する前にリストをコピーすることです。

for(GameUnit gu : new ArrayList<GameUnit>(this.getBase().getGameState().getAllUnits()))

または、コレクション自体を同期することもできます (これを機能させるには、「すべてのユニット」リストを変更している場所でも同期する必要があることに注意してください)。

ArrayList<GameUnit> units = this.getBase().getGameState().getAllUnits())
synchronized (units) {
  ...
}
于 2012-02-02T18:24:48.823 に答える
0

同じオブジェクト、たとえば MyObject を変更する 2 つのスレッドがあり、オブジェクトを同期しました。

いいえ、そうではありません。一方のスレッドのみが変更MyObjectされ、もう一方はブロックされています。

しかし、スレッドの 1 つで別のオブジェクトが変更されているため、MyObject を呼び出す必要があります。

ロックがレントラントであるため、ロックを保持しているスレッドは再び実行されます。

コメントが述べたように、投稿したコードは、その例外を取得するために実際に何をしているのかを示していません。

ですか?MyObject_ Collectionこのコレクションを別の場所で同時に変更していませんか? つまり、適切な同期をとっていませんか?
それとも繰り返しですか?
この場合、あなたが言う例外が発生します

于 2012-02-02T18:21:15.533 に答える
0

これを行うことはできません。これは循環ロジックです。

スレッドを完全に取り除き、評価の明示的な順序を決定するか、他の方法でデータを共有する必要があります。

考えられる戦略の 1 つは、「anotherObject.modify」の呼び出しを、次のように別の実行可能なスレッドに入れることです。

  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
       anotherObject.modify();
    }
  });
于 2012-02-02T18:24:29.960 に答える