SharedPreferences и безопасность потоков - PullRequest
47 голосов
/ 14 января 2011

Глядя на документы SharedPreferences он говорит:

"Примечание: в настоящее время этот класс не Поддержка использования в нескольких процессах. Это будет добавлено позже. "

Так что само по себе это не похоже на Thread Thread. Однако какие гарантии даются в отношении commit () и apply ()?

Например:

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

Будет ли гарантировано, что uniqueId всегда будет уникальным в этом случае?

Если нет, то есть ли лучший способ отслеживать уникальный идентификатор приложения, которое сохраняется?

Ответы [ 4 ]

85 голосов
/ 14 января 2011

Процессы и темы разные. Реализация 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.

6 голосов
/ 27 августа 2012

Мне было интересно то же самое - и наткнулся на этот поток , который говорит, что они не безопасны для потока:

Реализации Context.getSharedPreferences () и Editor.commit () не синхронизировать на одном мониторе.


С тех пор я посмотрел код Android 14 для проверки, и он довольно сложный. В частности, SharedPreferencesImpl, кажется, использует разные блокировки при чтении и записи на диск:

  • enqueueDiskWrite() блокировки на mWritingToDiskLock
  • startLoadFromDisk() блокируется на this и запускает блокировку потока на SharedPreferencesImpl.this

Я не уверен, что этот код действительно безопасен.

4 голосов
/ 07 сентября 2011

Вы должны знать, что SharedPreferences не работают на телефонах Samsung, посмотрите на проблему Android .

Я реализовал простое хранилище настроек базы данных, которое вы можете найти на github .

Приветствия

3 голосов
/ 14 января 2011

Я думаю, что это сделает.

Вы можете проверить это с помощью sleep внутри синхронизированного раздела и вызвать его из разных потоков

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...