SharedPreferences и безопасность потоков
Глядя на документы SharedPreferences, он говорит:
"Примечание: в настоящее время этот класс не поддерживает использование в нескольких процессах. Это будет добавлено позже".
Таким образом, сам по себе он не выглядит безопасным для потоков. Однако какие гарантии даются в отношении commit() и apply()?
Например:
synchronized(uniqueIdLock){
uniqueId = sharedPreferences.getInt("UNIQUE_INCREMENTING_ID", 0);
uniqueId++;
sharedPreferences.edit().putInt("UNIQUE_INCREMENTING_ID", uniqueId).commit();
}
Будет ли гарантировано, что uniqueId всегда будет уникальным в этом случае?
Если нет, есть ли лучший способ отслеживать уникальный идентификатор для приложения, которое сохраняется?
4 ответа
Процессы и темы разные. Реализация SharedPreferences в Android является поточно-ориентированной, но не процессно-безопасной. Обычно ваше приложение будет работать в одном и том же процессе, но вы можете настроить его в AndroidManifest.xml, так что, скажем, служба запускается в отдельном процессе, чем, скажем, действие.
Для проверки безопасности thready см. SharedPreferenceImpl ContextImpl.java из AOSP. Обратите внимание, что есть синхронизация, где бы вы ни ожидали.
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;
}
}
...
}
}
Однако для вашего случая уникального идентификатора кажется, что вы все равно хотите синхронизироваться, поскольку вы не хотите, чтобы он переключался между get и put.
Мне было интересно то же самое - и наткнулся на этот поток, который говорит, что они не являются потокобезопасными:
Реализации Context.getSharedPreferences() и Editor.commit () не синхронизируются на одном мониторе.
С тех пор я посмотрел на код Android 14, чтобы проверить, и это довольно сложно. конкретно SharedPreferencesImpl
Кажется, используются разные блокировки при чтении и записи на диск:
enqueueDiskWrite()
замки наmWritingToDiskLock
startLoadFromDisk()
замки наthis
и запускает блокировку потока наSharedPreferencesImpl.this
Я не уверен, что этот код действительно безопасен.
Вы должны знать, что SharedPreferences не работают на телефонах Samsung, обратите внимание на проблему с Android.
Я реализовал простое хранилище настроек базы данных, которое вы можете найти на github.
Ура,
Я думаю, что это сделает.
Вы можете проверить это с помощью sleep внутри синхронизированного раздела и вызывать его из разных потоков.