SharedPreferences and Thread Safety

AndroidThread SafetySharedpreferences

Android Problem Overview


Looking at the SharedPreferences docs it says:

> "Note: currently this class does not > support use across multiple processes. > This will be added later."

So in and of itself it doesn't appear to be Thread Safe. However, what kind of guarantees are made in regards to commit() and apply()?

For example:

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

Would it be guaranteed that the uniqueId was always unique in this case?

If not, is there a better way to keep track of a unique id for an application that persists?

Android Solutions


Solution 1 - Android

Processes and Threads are different. The SharedPreferences implementation in Android is thread-safe but not process-safe. Normally your app will run all in the same process, but it's possible for you to configure it in the AndroidManifest.xml so, say, the service runs in a separate process than, say, the activity.

To verify the thready safety, see the ContextImpl.java's SharedPreferenceImpl from AOSP. Note there's a synchronized wherever you'd expect there to be one.

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

However for your case of the unique id it seems you'd still want a synchronized as you don't want it to change between the get and the put.

Solution 2 - Android

I was wondering the same thing - and came across this thread that says they are not thread safe:

> The implementations of Context.getSharedPreferences() and Editor.commit () do not synchronize on the same monitor.


I have since looked at the Android 14 code to check, and it is quite involved. Specifically SharedPreferencesImpl seems to use different locks when reading & writing to disk:

  • enqueueDiskWrite() locks on mWritingToDiskLock
  • startLoadFromDisk() locks on this, and launches a thread locking on SharedPreferencesImpl.this

I'm unconvinced that this code really is safe.

Solution 3 - Android

I think that will do it.

You can test it using sleep inside the synchronized section and call it from different threads

Solution 4 - Android

You should be aware that SharedPreferences are not working on Samsung handsets, have a look at android issue.

I have implemented simple database preferences storage which you can find on github.

Cheers,

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncottonBallPawsView Question on Stackoverflow
Solution 1 - AndroidKevin TeslaCoilView Answer on Stackoverflow
Solution 2 - AndroidRichard Le MesurierView Answer on Stackoverflow
Solution 3 - AndroidPedro LoureiroView Answer on Stackoverflow
Solution 4 - AndroidMaciej ŁopacińskiView Answer on Stackoverflow