SharedPreferences and Thread Safety

旧城冷巷雨未停 提交于 2019-12-17 04:56:16

问题


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?


回答1:


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.




回答2:


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.




回答3:


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,




回答4:


I think that will do it.

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



来源:https://stackoverflow.com/questions/4693387/sharedpreferences-and-thread-safety

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!