一般的な構造はスレッドセーフではありません
プロセス全体を開始するスレッドがチェックmyMapし、場合によっては別のスレッドで実行を開始します。
if (myMap != null) {
doSomethingInAnotherThread();
}
// something can set `myMap` to null here...
実行がスケジュールされているコードは、ある時点で実行されます
void inAnotherThread() {
myMap.access();
}
myMapしかし、以前と同じであるという保証はもうありません。myMap参照するものを変更できるスレッドがある場合は、
void inAnotherThread() {
if (myMap != null) {
myMap.acess();
}
}
myMap2回アクセスし、毎回異なる可能性があるため、それでもスレッドセーフではありません。たとえば、内部では null ではありませんifが、null一度アクセスすると。解決策の 1 つは、参照をコピーして、作業中にその参照のローカル コピーを変更できないようにすることです。
void inAnotherThread() {
Map localReference = myMap;
if (localReference != null) {
localReference.acess();
}
}
それがスレッドセーフかどうかは、に依存しmyMapます。それがvolatile(またはfinal)であるかどうかにかかわらず。そうである場合: 他のスレッドは、参照されているものの最新バージョンを参照することが保証されmyMapます。そうでない場合: 何も保証されません。(注:内部で同期するため、事前発生runOnUiThread関係が確立されていると思います。したがって、参照の最新バージョンを表示するための何らかの保証が必要です)
正しいインスタンスへの参照を取得したら、次のポイントMapは、それを安全に使用できることです。simpleHashMapはスレッドセーフではありません。呼び出し.get()ても、別のスレッドがput/ remove/.. を呼び出し、.getアクセス中にデータを変更すると、まだ爆発する可能性があります。
他のスレッドが干渉できないように、アトミックのようCollections.synchronizedMap(map)な単一の操作を行うラップすることができます。getしかし、それでもすべてに対してスレッドセーフではありません。たとえば、外部で同期しないと、値の繰り返しは失敗します。ConcurrentHashMapこの問題は、反復もサポートする を使用することで解決できます。
スレッドセーフは、多くの要因と、スレッドセーフとは何かの定義に依存します。myMap一度設定すると決して変更されないことを保証でき!= null、バックグラウンド スレッドの変更が完了myMapしているため、UiThread が安全にアクセスできることがわかっている場合、記述した内容はすでにスレッドセーフです。