4

スレッド A で実行され、このようなローカル変数リストを作成するコントローラー クラスがあります。

スレッドA

list = new ArrayList<Map<String, Order>>();
list.add(...);
list.add(...);

ここで、Order は、String、int、long などのいくつかのプリミティブ プロパティを持つ Java Bean です。

このリストが作成されると、その参照がアクティビティの UI スレッド (スレッド B) に渡され、そこでアクセスされます。クロススレッド通信は、Handler クラス + post() メソッドを使用して行われます。

問題は、まったく同期せずにスレッド B からリスト データにアクセスできるかどうかです。スレッド A で構築された後、リストはまったくアクセス/変更されないことに注意してください。ローカル変数のように存在し、後でスレッド B に渡されます。

4

4 に答える 4

2

安全。メッセージ キューで行われる同期により、先行発生関係が確立されます。もちろん、これは後でマップを変更しないことを前提としています。また、マップなどに含まれるオブジェクトは、適切な同期なしに他のスレッドによって変更されてはなりません。

つまり、リストとその中のデータが B 以外のスレッドによって変更されていない場合、それ以上の同期は必要ありません。

于 2013-07-25T15:30:53.007 に答える
1

あなたが提供する文脈から、これがどこで起こるかは明らかではありません:

list = new ArrayList<Map<String, Order>>();
list.add(...);
list.add(...);

それがコンストラクター内にあり listfinal 参照がコンストラクターthisからリークせず、それが変更されないことが絶対に確実である場合(たとえば、デコレーター メソッドを使用することによって) インスタンスへの参照が他の場所からアクセスできない場合同期を使用しなくてもかまいません。そうしないと、頭上にダモクレスの剣があります。listunmodifiableListOrder

Order他の場所から変更しても例外は発生しない可能性がありますが、データの不整合や破損につながる可能性があるため、参照について言及しました。

于 2013-07-25T15:29:34.683 に答える
-3

はい、データを読み取るだけの場合は同期する必要はありません。

スレッド B (またはその他の数のスレッド) がリストにアクセスしている間に、スレッド A が最終的にリストを変更する場合でも、ライターは常に 1 つしか存在しないため、同期する必要はありません。

申し訳ありませんが、上記のステートメントは完全に正しくありません。JavaDoc に記載されているように:

複数のスレッドが ArrayList インスタンスに同時にアクセスし、少なくとも 1 つのスレッドがリストを構造的に変更する場合は、外部で同期する必要があります。(構造変更とは、1 つまたは複数の要素を追加または削除する操作、または補助配列のサイズを明示的に変更する操作です。単に要素の値を設定するだけでは、構造変更にはなりません。)

また、要素の変更は考慮していませんが、純粋にリストの変更を考慮していることにも注意してください。

于 2013-07-25T15:12:02.600 に答える