大家都知道Core data本身并不是一个并发安全的架构;不过针对多线程访问带来的问题,Apple给出了很多指导;同时很多第三方的开发者也贡献了很多解决方法。不过最近碰到的一个问题很奇怪,觉得有一定的特殊性,与大家分享一下。

这个问题似乎在7.0.1以前的版本上并不存在;不过后来我升级版本到了7.0.4。app的模型很简单,主线程在前台对数据库进行读写,而后台线程不断地做扫描(只读)。为此每个线程中各创建了一个NSManagedObjectContext。

这个模型其实有点奇怪,因为普遍的模型是颠倒过来的——后台线程做读写更新,而主线程只读;但是由于我的app的特殊性,并且读写性能并不关键,所以我并不想花很大力气去扭曲逻辑自然的结构,还是保持这个模型。不过问题也因此而来:我发现主线程写入的数据,后台线程读出来的并不一致,而是写入之前的值,即使我重新做了完整的fetch。

按照Apple文档和其他第三方资料的说明,主程序用context save后,这个改动就一定被persistent了;那么后台线程fetch怎么可能读出以前的值?机器是不会错的,既然读出的是以前的值,那么肯定是后台线程的context在哪里cache了一份。但是fetch操作无论如何应该返回persistent store里的值啊?而且insert/delete操作的修改,确实都反应出来了,唯有对property值的修改,还是旧的数值;

大量的有关并发问题的第三方讨论文章显示的是相反的问题:如果在后台线程做了修改,那么需要merge到主线程。但是这个merge影响到的只是NSFetchResultsController的内容,对于不merge造成的后果,所有的文章都众口一词:除非re-fetch或者re-fault,否则数据当然会不一致。也就是说,如果re-fetch,那么数据还是可以保持一致的。然而实际的测试证明即使是re-fetch了,还是无法反应change的数值。

最终只能怀疑re-fetch仍然不是彻底地从persistent storage里面重新load整个model。虽然insert/delete的对象确实重新load了,但是change的property确确事实没有被更新;NSManagedObjectContext 对fetch实现的机制,应该还是在内存里留了一份model的cache。为了彻底清楚这个cache,对后台线程的context进行reset后,果然一切都正常了。

iOS Core data多线程并发访问的问题的更多相关文章

  1. Cocos2d-x优化中多线程并发访问

    多线程并发访问在Cocos2d-x引擎中用的不是很多,这主要是因为中整个结构设计没有采用多线程.源自于Objective-C的Ref对象,需要使用AutoreleasePool进行内存管理,Autor ...

  2. Java并发编程(03):多线程并发访问,同步控制

    本文源码:GitHub·点这里 || GitEE·点这里 一.并发问题 多线程学习的时候,要面对的第一个复杂问题就是,并发模式下变量的访问,如果不理清楚内在流程和原因,经常会出现这样一个问题:线程处理 ...

  3. 正确使用Core Data多线程的3种方式

    在#Pragma Conference 2015会议上,Marcus Zarra,撰写过关于Core Data和Core Animation的书,叙述了三种在多线程环境下使用Core Data的方法并 ...

  4. iOS:Core Data 中的简单ORM

    我们首先在xcdatamodel文件中设计我们的数据库:例如我建立一个Data的实体,里面有一个String类型的属性name以及一个Integer类型的num: 然后选中Data,添加文件,选择NS ...

  5. iOS: Core Data入门

    Core Data是ORM框架,很像.NET框架中的EntityFramework.使用的基本步骤是: 在项目属性里引入CoreData.framework (标准库) 在项目中新建DataModel ...

  6. IOS - CORE DATA的目录(xcode6)

       当使用coredata作为app的后台数据存储介质后,我们很想知道数据是否成功插入.为此,我想找到coredata.sqlite的文件 代码中指定的存储目录为: - (NSURL *)appli ...

  7. Core Data 多线程时多个context使用

    原文地址:http://blog.csdn.net/willmomo/article/details/19759413 写的非常好!我这里截取一点重要的,备份,请去原地址阅读! 本人去年10月份才接触 ...

  8. iOS Core Data 数据库的加密(待研究)

    https://github.com/project-imas/encrypted-core-data 使用起来很方便,底层还是使用了SQLCipher,有时间要研究一下! 数据库的密码不能用固定字符 ...

  9. iOS-Core Data 详解

    使用Core Data 框架 Core Data框架本质就是一个ORM(对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一 ...

随机推荐

  1. ZOJ 3872 Beauty of Array (The 12th Zhejiang Provincial Collegiate Programming Contest )

    对于没有题目积累和clever mind的我来说,想解这道题还是非常困难的,也根本没有想到用dp. from: http://blog.csdn.net/u013050857/article/deta ...

  2. apache Internal Server Error 的几个问题

    Internal Server Error The server encountered an internal error or misconfiguration and was unable to ...

  3. 在ASP.NET中发送电子邮件的实例教程

    首先.导入命名空间: 代码如下 复制代码 using System.Net.Mail; 定义发送电子邮件的方法[网上很多不同的,可以对比着看一下,WinForm的也适用]: 代码如下 复制代码 /// ...

  4. 【学习笔记】Xcode常见设置

    一.设置主题和字体大小    二.设置显示代码行号

  5. button等按钮onclientclick事件失效

    如果确定JS没写错 第一种方法: 在JS方法最后return false; 调用方法前加上return 第二种方法: 在JS方法最后event.returnValue=false; 附加:event. ...

  6. C# 线程--第一单线程基础

    概念 什么是进程? 当一个程序被打开运行时,它就是一个进程.在进程中包括线程,进程可以由一个或多个线程组成. 什么是线程? 线程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC), ...

  7. Python 字典(Dictionary) setdefault()方法

    描述 Python 字典(Dictionary) setdefault() 函数和get()方法类似, 如果键不已经存在于字典中,将会添加键并将值设为默认值. 语法 setdefault()方法语法: ...

  8. [前端插件]Bootstrap Table服务器分页与在线编辑应用总结

    先看Bootstrap Table应用效果: 表格用来显示数据库中的数据,数据通过AJAX从服务器加载,同时分页功能有服务器实现,避免客户端分页,在加载大量数据时造成的用户体验不好.还可以设置查询数据 ...

  9. 正确编写Designated Initializer的几个原则

    Designated Initializer(指定初始化器)在Objective-C里面是很重要的概念,但是在日常开发中我们往往会忽视它的重要性,以至于我们写出的代码具有潜藏的Bug,且不易发现.保证 ...

  10. SQL语句执行顺寻

    SQL语句执行的时候是有一定顺序的.理解这个顺序对SQL的使用和学习有很大的帮助. 1.from 先选择一个表,或者说源头,构成一个结果集. 2.where 然后用where对结果集进行筛选.筛选出需 ...