共有されている展開とスレッドの安全
-
11-10-2019 - |
質問
を見ています SharedPreferencesドキュメント それは言う:
「注:現在、このクラスは複数のプロセスにわたる使用をサポートしていません。これは後で追加されます。」
したがって、それ自体では、糸が安全であるようには見えません。ただし、commit()とapply()に関してどのような保証が行われますか?
例えば:
synchronized(uniqueIdLock){
uniqueId = sharedPreferences.getInt("UNIQUE_INCREMENTING_ID", 0);
uniqueId++;
sharedPreferences.edit().putInt("UNIQUE_INCREMENTING_ID", uniqueId).commit();
}
この場合、UniqueIDが常にユニークであったことは保証されますか?
そうでない場合、持続するアプリケーションの一意のIDを追跡するより良い方法はありますか?
解決
プロセスとスレッドは異なります。 AndroidでのSharedPreferencesの実装はスレッドセーフですが、プロセスセーフではありません。通常、アプリはすべて同じプロセスですべて実行されますが、AndroidManifest.xmlで構成することができます。たとえば、サービスはアクティビティよりも別のプロセスで実行されます。
スレッドの安全性を確認するには、AOSPのContextImpl.javaの共有PreferenceImplを参照してください。注意してください。
private static final class SharedPreferencesImpl implements SharedPreferences {
...
public String getString(String key, String defValue) {
synchronized (this) {
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
...
public final class EditorImpl implements Editor {
public Editor putString(String key, String value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
...
}
}
ただし、一意のIDの場合、GetとPutの間に変更したくないため、まだ同期したいと思われます。
他のヒント
私は同じことを疑問に思っていました - そして出会いました このスレッド それは彼らが糸が安全ではないと言っています:
Context.GetSharedPreferences()およびEditor.Commit()の実装は、同じモニターで同期しません。
それ以来、チェックするAndroid 14コードを見てきましたが、それは非常に関与しています。具体的には SharedPreferencesImpl
ディスクへの読み取りと書き込みの際に、異なるロックを使用しているようです:
enqueueDiskWrite()
ロックしますmWritingToDiskLock
startLoadFromDisk()
ロックしますthis
, 、およびロックオンスレッドを起動しますSharedPreferencesImpl.this
このコードは本当に安全であることに納得できません。
SharedPreferencesがSamsungの携帯電話で機能していないことに注意する必要があります。 Androidの問題.
あなたが見つけることができる簡単なデータベース設定ストレージを実装しました github.
乾杯、
私はそれがそれをするだろうと思います。
同期セクション内の睡眠を使用してテストし、異なるスレッドから呼び出すことができます