You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android SharedPreferences apply()方法是否存在竞态条件?

SharedPreferences.apply() 是否存在竞态条件风险?

没错,apply()确实容易受到竞态条件的影响,这得从它的异步提交机制和SharedPreferences的设计细节说起:

  • 内存即时更新与异步磁盘写入的顺序差
    apply()会立刻把变更同步到内存中的SharedPreferences对象,但磁盘写入任务会被放到一个后台单线程队列中依次执行。如果多个线程连续调用apply()修改同一个或不同的key,内存里的状态会是最新的,但磁盘上的状态会严格按照任务提交顺序更新。如果在磁盘写入完成前进程意外终止,队列中未执行的apply()任务会丢失,导致磁盘最终的持久化状态和内存中的最新状态不一致——这就是典型的竞态导致的数据丢失场景。

  • 跨线程操作缺乏强原子性保障
    虽然官方文档提到SharedPreferences实例是线程安全的,但Editor对象并非如此。如果多个线程同时获取独立的Editor实例修改不同的key,随后调用apply(),内存中的更新是即时生效的,但磁盘写入是多个独立的异步任务。如果在这些任务执行过程中进程崩溃,可能部分变更被写入磁盘,部分丢失,最终出现磁盘状态和内存状态不匹配的情况。

  • 无回调导致的依赖逻辑失效
    和commit()不同,apply()没有返回值,也不会通知磁盘写入是否成功。如果你的业务逻辑依赖于磁盘写入完成后的状态(比如后续读取磁盘文件做校验),在apply()调用后立刻执行这类逻辑,就可能读取到旧的磁盘数据,和内存中的最新值产生冲突,这也是一种竞态条件的表现。

如果要规避这类风险,你可以根据场景选择方案:

  • 若不担心主线程阻塞,使用commit()同步提交,确保变更立刻持久化;
  • 对多线程修改的场景,自己添加同步锁(比如针对SharedPreferences实例加锁),保证修改操作的原子性;
  • 对数据一致性要求高的场景,考虑使用更可靠的线程安全持久化方案(比如Room数据库)。

内容的提问来源于stack exchange,提问作者Shawn Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:32:43