2011-01-14 14 views
42

Mit Blick auf den SharedPreferences docs heißt es:SharedPreferences und Threadsicherheit

„Hinweis: zur Zeit diese Klasse nicht Unterstützung Verwendung über mehrere Prozesse Dies später hinzugefügt werden..“

So an und für sich scheint es nicht Thread Safe. Welche Art von Garantien gibt es in Bezug auf commit() und apply()?

Zum Beispiel:

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

Wäre es garantiert werden, dass die UniqueId in diesem Fall immer einzigartig war?

Wenn nicht, gibt es einen besseren Weg, eine eindeutige ID für eine Anwendung zu behalten, die fortbesteht?

+3

Der Beispielcode wird mit dem nicht endgültigen Feld synchronisiert und ändert es. Ich bezweifle, dass du das willst. – Bloodboiler

+1

Hoppla, schöner Fang. – cottonBallPaws

+1

Was ist der 'uniqueIdLock'? Wo ist es definiert? Ist es statisch, final public etc? Vielleicht solltest du auch die angenommene Antwort wechseln? –

Antwort

77

Prozesse und Threads unterschiedlich sind nennen. Die SharedPreferences-Implementierung in Android ist Thread-sicher, aber nicht prozesssicher. Normalerweise wird Ihre App alle im selben Prozess ausführen, aber Sie können es in der AndroidManifest.xml konfigurieren, dh der Dienst wird in einem anderen Prozess ausgeführt als beispielsweise die Aktivität.

Zur Überprüfung der Sicherheit von Threads siehe ContextImpl.java SharedPreferenceImpl von AOSP. Beachten Sie, dass dort synchronisiert wird, wo auch immer Sie es erwarten.

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

jedoch für Ihren Fall der einzigartigen ID es scheint, dass Sie noch ein synchronisiertes wollen würde, wie Sie es zwischen dem zu bekommen und die Put-zu nicht ändern wollen.

+0

bezieht sich der "This" -Teil des "synchronisierten (this)" -Aufrufs auf das äußere Objekt oder auf die inneren Objekte? Ich fand eine Referenz auf Google-Gruppen, die besagt, dass sich das Schloss auf verschiedenen Objekten befindet - nicht sicher, ob das richtig ist oder nicht. –

+0

@Richard: Sie können nicht aus dem Schnipsel oben erkennen, aber gelegentliche Inspektion sagt, dass der Code threadsicher ist. Es gibt zwei verschiedene Sperren - eine für eine Instanz von SharedPreferencesImpl, die andere für eine Instanz von EditorImpl -, aber die verschiedenen Dinge schützen: mMap und mModified. –

+0

@ G.BlakeMeike: mit der Ausnahme, dass "mMap" und "mModified" in der gleichen Datei gelesen und geschrieben werden, deren Zugriff auf verschiedene Monitore zu sperren scheint. Ich habe den Code jedoch nur beiläufig begutachtet und keine Stresstests durchgeführt. (Antwort aktualisiert) –

3

Ich denke, das wird es tun.

Sie können es Schlaf in dem synchronisierten Abschnitt mit testen und von verschiedenen Threads

4

Sie sollten beachten, dass SharedPreferences nicht auf Samsung-Handys funktionieren, sehen Sie sich android issue an.

Ich habe einfache Datenbank Einstellungen Speicher implementiert, die Sie auf github finden können.

Cheers,

+1

wow, wie die Kinder sagen würden, Epic Fail. – StackOverflowed

+1

Weiß jemand, ob das immer noch so ist? Oder werden die meisten Galaxy S-Benutzer inzwischen auf einige Bugfixed-Versionen aktualisiert? Wenn man bedenkt, wie beliebt die Galaxy S-Modelle sind, würde ich dies als eine große rote Flagge für SharedPreferences bezeichnen - ist das richtig? – skrebbel

+0

Denke nicht, dass es heute ein Problem ist –

4

ich das Gleiche fragen - und stieß auf this thread, das sagt sie nicht Thread-sicher sind:

Die Implementierungen von Context.getSharedPreferences() und Editor.commit () Synchronisieren Sie nicht auf demselben Monitor.


Ich habe im Android 14 Code zu überprüfen, da sah, und es ist recht kompliziert.Spezifisch SharedPreferencesImpl scheint verschiedene Schlösser zu verwenden, wenn & Schreiben auf die Festplatte zu lesen:

  • enqueueDiskWrite() Sperren auf mWritingToDiskLock
  • startLoadFromDisk() Sperren auf this und startet eine Gewindesicherung auf SharedPreferencesImpl.this

I‘ Ich bin nicht überzeugt, dass dieser Code wirklich sicher ist.

+1

Das Zitat ist korrekt: Die Synchronisierung erfolgt nicht auf demselben Monitor. Auf der anderen Seite sehe ich nicht aus dem gelegentlichen Lesen des Codes, warum sie sollten. Nochmals, nur ein kurzer Lesevorgang, aber an der einzigen Stelle, an der ich bemerkt habe, dass sie auf den freigegebenen veränderbaren Zustand zugreifen, benutzen * die * denselben Monitor. –