1

同じオブジェクトを変更する2つのスレッドがあります。オブジェクトは、ArrayList(ベクトルではなく)のカスタムの同期されていないオブジェクトです。これらの2つのスレッドは同時に呼び出されるため、これら2つのスレッドをうまく連携させたいと思います。

これがスレッド1の唯一の重要なメソッドです。

public void doThread1Action() {
  //something...
  for(myObject x : MyArrayList){
    modify(x);
  }
}

これがスレッド2のメソッドです:

public void doThread2Action() {   
  //something...
  for(myObject x : MyArrayList){
    modifyAgain(x);
  }
}

現時点では、テスト時に「ConcurrentModificationExceptions」が発生することがあります。(スレッド2がオブジェクトを変更しようとする前に、スレッド1が反復を完了する速度に依存すると思います。)

synchronizedこれらの2つのメソッドの先頭に追加するだけで、スレッドは同期された方法で連携し、アクセスを試みないだろうと私は考えていArrayListますか?または、をに変更する必要ArrayListがありVectorますか?

4

4 に答える 4

3

ConcurrentModificationExceptionは、コレクション内のオブジェクトの変更ではなく、イテレータがアクティブなときにコレクションに追加/コレクションから削除することから発生します。

共有リソースはコレクションであり、追加/削除を使用する3番目の方法が必要です。同時実行を正しく行うには、コレクションリソースにアクセスするすべてのメソッドでコレクションリソースへのアクセスを同期する必要があります。

過度に長い同期ブロックを回避するための一般的なパターン、同期ブロック内のコレクションをコピーしてから、それを反復処理することです。このようにすると、最初に話している問題(オブジェクトの同時変更)が再び発生することに注意してください。ただし、今回は別のリソースをロックできます。

于 2012-05-12T11:03:34.960 に答える
0

リストを構造的に変更しない限り、つまりリストにオブジェクトを追加またはリストから削除しない限り、リストへのアクセスを同期する必要はありません。またConcurrentModificationException、リストを構造的に変更した場合にのみスローされるため、sは表示されません。

したがって、リストに含まれるオブジェクトのみを変更し、リスト上のオブジェクトを追加、削除、または並べ替えない場合、次のように、変更するたびに含まれるオブジェクトを同期することができます。

void modifyAgain(MyObject x) {
    synchronized(x) {
        // do the modification
    }
}

リスト内の2つの異なるオブジェクトを同時に変更できないためsynchronized、メソッドで修飾子を使用しません。modifyAgain()

もちろん、他のスレッドのmodify()メソッドは、と同じ方法で実装する必要がありますmodifyAgain()

于 2012-05-12T11:14:25.760 に答える
0

同じロックでコレクションへのアクセスを同期する必要があるため、メソッドでsynchronizedキーワードを使用するだけで(異なるクラスにあると仮定して)、2つの異なるオブジェクトがロックされます。

だからここにあなたがする必要があるかもしれないことの例があります:

Object lock = new Object();

public void doThread1Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
           modify(x);
    }

}

public void doThread2Action(){

//something...
    synchronized(lock){
        for(myObject x : MyArrayList){
            modifyAgain(x);
    }

}

CopyOnWriteArrayListまた、代わりに使用することを検討できますVector

于 2012-05-12T11:19:16.513 に答える
0

あなたの問題はに関連していると思いますConcurrentModificationException。Javaドキュメントのこのクラスは次のように述べています。

/ ** *この例外 は、オブジェクトの同時変更が許可されていない場合に*そのような変更を
検出したメソッドによってスローされる可能性があります。

* /

あなたの場合、問題はリスト内のイテレータであり、変更される可能性があります。次の実装によって、あなたの問題は唯一のものになると思います:

public void doThread1Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modify(x);
       }
    }
}

その後:

public void doThread2Action()
{
    synchronized(x //for sample)
    {
       //something...
       for(myObject x : MyArrayList)
       {
          modifyAgain(x);
       }
    }
}

より良い結果を得るために、私は誰かに私の解決策を修正してもらいたい。

于 2012-05-12T11:19:40.067 に答える