2011-01-14 147 views
42

望着SharedPreferences docs它说:SharedPreferences和线程安全

“注:目前这一类确实在多个流程不 支持使用 这将在以后添加。”

因此,它本身看起来并不是线程安全的。然而,对commit()和apply()做出了什么样的保证呢?

例如:

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

会是保证了UNIQUEID总是在这种情况下独特之处?

如果没有,是否有更好的方法来跟踪持续存在的应用程序的唯一ID?

+3

示例代码与非最终字段同步并对其进行更改。我怀疑你想这样做。 – Bloodboiler 2013-02-07 15:07:46

+1

哎呀,很好。 – cottonBallPaws 2013-02-07 16:55:16

+1

什么是uniqueIdLock?它在哪里定义?它是静态的,最终的公众等?也许你应该转换接受的答案? – 2013-09-18 15:27:24

回答

77

进程和线程都是不同的调用它。 Android中的SharedPreferences实现是线程安全的,但不是流程安全的。通常,您的应用程序将在同一个进程中运行,但您可以在AndroidManifest.xml中配置它,因此,服务在单独的进程中运行,而不是在活动中运行。

要验证安全性,请参阅AOSP中的ContextImpl.java的SharedPreferenceImpl。请注意,无论您希望哪里有一个,都可以实现同步。

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

但是你唯一ID的情况下,它似乎你还是希望有一个同步的,你不希望它get和看跌之间切换。

3

我认为这样做。

您可以使用同步段内睡眠测试,并从不同的线程

4

你应该知道SharedPreferences在三星手机上没有工作,看看android issue

我已经实现了简单的数据库首选项存储,您可以在github上找到它。

干杯,

4

我想知道同样的事情 - 和整个this thread,说他们不是线程安全的传来:

Context.getSharedPreferences()和Editor.commit 的实现()不要在同一台显示器上同步。


我后来看了一下Android的代码14来检查,这是相当复杂。具体SharedPreferencesImpl似乎用不同的锁阅读&写入磁盘时:在thismWritingToDiskLock

  • startLoadFromDisk()

    • enqueueDiskWrite()锁,并启动对SharedPreferencesImpl.this

    我一个线程锁定米不相信这个代码真的是安全的。