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?
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.
Shared preferences allow you to store small amounts of primitive data as key/value pairs in a file on the device. To get a handle to a preference file, and to read, write, and manage preference data, use the SharedPreferences class. The Android framework manages the shared preferences file itself.
I've noticed that a lot of projects have their SharedPreferences code scattered all over the project. The reason for this mostly is that fetching SharedPreference and reading/writing preferences as and when needed is the easiest thing to do when writing an app.
If you have a relatively small collection of key-values that you'd like to save, you should use the SharedPreferences APIs. A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With