web-dev-qa-db-fra.com

Préférences partagées et sécurité des threads

En regardant les Documents de SharedPreferences il dit:

"Remarque: actuellement, cette classe ne prend pas en charge l'utilisation sur plusieurs processus. Cela sera ajouté plus tard."

Donc, en soi, il ne semble pas être Thread Safe. Cependant, quels types de garanties sont accordées en ce qui concerne commit () et apply ()?

Par exemple:

synchronized(uniqueIdLock){
   uniqueId = sharedPreferences.getInt("UNIQUE_INCREMENTING_ID", 0);
   uniqueId++;
   sharedPreferences.edit().putInt("UNIQUE_INCREMENTING_ID", uniqueId).commit();
}

Serait-il garanti que l'uniqueId a toujours été unique dans ce cas?

Sinon, existe-t-il un meilleur moyen de garder une trace d'un identifiant unique pour une application qui persiste?

47
cottonBallPaws

Les processus et les threads sont différents. L'implémentation de SharedPreferences dans Android est adaptée aux threads mais pas aux processus. Normalement, votre application s'exécutera toutes dans le même processus, mais il vous est possible de la configurer dans AndroidManifest.xml, donc, par exemple, le service s'exécute dans un processus distinct de, disons, l'activité.

Pour vérifier la sécurité complète, consultez SharedPreferenceImpl de ContextImpl.Java d'AOSP. Notez qu'il y a un synchronisé partout où vous vous attendez à ce qu'il y en ait un.

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;
            }
        }
    ...
    }
}

Cependant, pour votre cas de l'identifiant unique, il semble que vous souhaitiez toujours un synchronisé car vous ne voulez pas qu'il change entre le get et le put.

85
Kevin TeslaCoil

Je me demandais la même chose - et je suis tombé sur ce fil qui dit qu'ils ne sont pas sûrs pour les fils:

Les implémentations de Context.getSharedPreferences () et Editor.commit () ne se synchronisent pas sur le même moniteur.


J'ai depuis regardé le code Android 14 à vérifier, et il est très impliqué. Plus précisément, SharedPreferencesImpl semble utiliser différents verrous lors de la lecture et de l'écriture sur le disque:

  • enqueueDiskWrite() verrouille sur mWritingToDiskLock
  • startLoadFromDisk() se verrouille sur this et lance un verrouillage de thread sur SharedPreferencesImpl.this

Je ne suis pas convaincu que ce code soit vraiment sûr.

6
Richard Le Mesurier

Vous devez savoir que SharedPreferences ne fonctionne pas sur les combinés Samsung, jetez un œil à problème Android .

J'ai mis en place un stockage simple des préférences de base de données que vous pouvez trouver sur github .

À votre santé,

4

Je pense que cela suffira.

Vous pouvez le tester en utilisant sleep dans la section synchronisée et l'appeler à partir de différents threads

3
Pedro Loureiro