ArrayListが同期されていないとはどういう意味ですか?
オブジェクトスコープでArrayListを宣言すると、オブジェクトにアクセスする複数のスレッドがリストを変更する機会があるということですか?
ArrayListが同期されていないとはどういう意味ですか?
これは、複数のスレッドからArrayList
インスタンスにアクセスすることが安全でない可能性があることを意味します(「予期しない動作が発生する可能性がある」または「宣伝どおりに機能しない可能性がある」と読んでください)。
参考文献:
オブジェクトスコープでArrayListを宣言すると、オブジェクトにアクセスする複数のスレッドがリストを変更する機会があるということですか?
スレッドセーフであったとしても、複数のスレッドがリストを変更できます。
違いは、スレッドセーフではなく、複数のスレッドがリストにアクセスする場合、すべての賭けが無効になることです。クラスがスレッドセーフではないと言うことは、すべてのメソッドの説明の前に「一度に1つのスレッドからアクセスする場合、このメソッドは次のように機能します.....」を追加することと同じです。
同期されているかどうかに関係なく、ArrayListは常に複数のスレッドによって変更できます。同期とは、同時アクセスを防ぐことです。
ArrayList(または一般にコレクション)では、2つの並行性の問題があります。
最初、メソッドの同期があります。これは、ArrayListインスタンスのメソッドへのすべての呼び出しが同期されることを意味します。したがって、一度に実行されるメソッドは常に1つだけです。最初のメソッドがまだ計算している間に発生する他のすべてのメソッド呼び出しは、実行中のメソッドが完了するまでキューに入れられます。
メソッドの同期は、次のようにArrayListをラップすることで保証できます。
List list = Collections.synchronizedList(new ArrayList());
例:2つのスレッドが同時に次のことを実行しようとするとします。
list.add(0, "test");
同期されたリストがある場合、リストのあとがきが2つの「テスト」エントリで始まることが保証されます。リストが同期されていない場合、「テスト」エントリが1つしかないリスト、またはその他の予期しない結果が発生する可能性があります。
2番目、インスタンスの同期があります。ここでは、同時メソッド呼び出しを防ぐだけでなく、一度に1つのスレッドだけがリストオブジェクトにアクセスできるようにします。これは、ロジックが完了するまでリストを変更しない状態のままにする必要があるロジックがある場合に重要です。たとえば、リストを反復処理します。リストを反復処理している間、他のスレッドが要素を追加することは望ましくありません。
この種の同期は、ロジックの一部を同期ブロックでラップすることによって行われます。
synchronized(list) {
for (Object o:list) {
...
}
}
オブジェクトスコープでArrayListを宣言すると、オブジェクトにアクセスする複数のスレッドがリストを変更する機会があるということですか?
はい。複数のスレッドが同時に動作する場合、予期しない動作が発生する可能性があります
これは、ArrayListのインスタンスがスレッドセーフであることが保証されていないことを意味します。これには通常、読み取りアクセスと書き込みアクセスの両方が含まれます。外部同期なしでこれを行うと、オブジェクトをスタンジ状態のままにして、動作をデバッグするのが困難になる可能性があります。
同期されているということは、すべての操作がスレッドセーフであることを意味します。2つのスレッドから同じベクトルを同時に使用する場合、状態を破壊することはできません。ただし、これにより速度が低下します。
シングルスレッド環境で作業している場合(またはリストがスレッドに制限されて共有されていない場合)は、ArrayListを使用します。同じコレクションを共有する複数のスレッドを使用している場合は、Vectorを使用するか、ArrayListを使用しますが、他の方法(手動またはラッパーなど)で同期します。
同期されているということは、すべての操作がスレッドセーフであることを意味します。2つのスレッドから同じ配列リストを同時に使用する場合、それらは状態を破壊できません。ただし、これにより速度が低下します。
デフォルトでは、ArrayListは同期されていませんが、synchronizedキーワードで実現できます。
ArrayList al=new ArrayList();
Collections.synchronized(al);