关于CoreData和SQLite多线程访问时的线程安全问题
数据库读取操作一般都是多线程访问的。在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱。
IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问。
一:FMDB的线程安全:(以读取图片为例)
1.没有线程安全的执行方式:
//************** 数据库保存图片 ******************//
FMDatabase *database = [FMDatabase databaseWithPath:[self getDatabasePath]];
//打开数据库
[database open];
NSString *sql = @"create table if not exists Test (id integer primary key autoincrement,name text,image blob);";
//创建表
[database executeUpdate:sql];
//把UIImage对象转化为NSData
NSData *data = UIImagePNGRepresentation([UIImage imageNamed:@"user_browse"]);
//写入数据
sql = @"insert into Test (name,image) values (?,?)";
[database executeUpdate:sql,@"张三",data];
//读取显示
sql = @"select * from Test;";
FMResultSet *resultSet = [database executeQuery:sql];
while (resultSet.next)
{
//[resultSet dataForColumn:@"image"];
NSData *imageData = [resultSet dataForColumnIndex:2];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
imageView.image = [UIImage imageWithData:imageData];
[self.view addSubview:imageView];
}
2,使用线程队列
//************** 数据库线程安全 ***********//
FMDatabaseQueue *queue = [[FMDatabaseQueue alloc] initWithPath:[self getDatabasePath]];
[queue inDatabase:^(FMDatabase *db) {
//线程安全的
__block NSString *sql = @"create table if not exists Test (id integer primary key autoincrement,name text,image blob);";
//创建表
[database executeUpdate:sql];
}];
//插入数据
[queue inDatabase:^(FMDatabase *db) {
//写入数据
sql = @"insert into Test (name,image) values (?,?)";
[database executeUpdate:sql,@"张三",data];
}];
//读取
[queue inDatabase:^(FMDatabase *db) {
//读取显示
sql = @"select * from Test;";
FMResultSet *resultSet = [database executeQuery:sql];
while (resultSet.next)
{
//[resultSet dataForColumn:@"image"];
NSData *imageData = [resultSet dataForColumnIndex:2];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
imageView.image = [UIImage imageWithData:imageData];
[self.view addSubview:imageView];
}
}];
分析一下线程安全下的FMDB的实现:
在当使用FMDBDatabaseQueue创建数据库时,会使用GCD创建一个线程队列:
。。。
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
_openFlags = openFlags;
。。。
然后在读取时调用[queue inDatabase:^(FMDatabase *db)
方法,在block中会锁定当前数据库
dispatch_sync(_queue, ^() {
FMDatabase *db = [self database];
block(db);
……
}
我们可以看到实际上这里是对整个数据库进行加锁,以此来保证线程安全的。
二、CoreData的线程安全
1.没有线程安全的coredata数据读取:
NSManagedObjectContext对象的创建:_managedObjectContext = [[NSManagedObjectContext alloc] init];
插入数据操作:(AppDetailModal为数据模型)
context 为返回的 _managedObjectContext
AppDetailModal *newapp = [NSEntityDescription insertNewObjectForEntityForName:TableName inManagedObjectContext:context];
其他查询、更新、删除操作
//获取Entity
NSEntityDescription *entity = [NSEntityDescription entityForName:TableName inManagedObjectContext:context];
2.线程安全的coreData操作:
首先创建并行的NSManagedObjectContext对象
NSManagedObjectContext* context=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
然后在执行读取操作时使用一下两个方法:
-(void)performBlock:(void (^)(void))block
-(void)performBlockAndWait:(void (^)(void))block
[context performBlock:^{
//要执行的读取操作
}];
Written with StackEdit.
关于CoreData和SQLite多线程访问时的线程安全问题的更多相关文章
- CoreData和SQLite多线程访问时的线程安全问题
数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两 ...
- CoreData和SQLite多线程访问时的线程安全
关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常 ...
- redis是单进程数据库,多用户排队对统一数据进行访问,不存在并发访问生产的线程安全问题
redis是单进程数据库,多用户排队对统一数据进行访问,不存在并发访问生产的线程安全问题. oracle是多进程数据库,存在并发访问的问题,必须事务加锁等方式进行处理.
- (原创)android Sqlite多线程访问异常解决方案
在开发Android的程序的时候sqlite数据库是经常用到的:在多线程访问数据库的时候会出现这样的异常:java.lang.IllegalStateException: Cannot perform ...
- C# - 多线程 之 进程与线程
并行~并发 并发 Concurrency,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤 ...
- IOS 使用FMDB多线程访问数据库 及databaseislocked的问题
原理:文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写.在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译s ...
- SQLite多线程写锁文件解决方案
在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题. 思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作:其他线程来写时,需要先检测是否有进程正在 ...
- 使用FMDB多线程访问数据库,及database is locked的问题
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...
- Sqlite多线程相关整理
Sqlite多线程相关整理 Sqlite With MultiThreads 什么是线程安全? 当多个线程访问某个方法时,不管你通过怎样的调用方式.或者说这些线程如何交替地执行,我们在主程序中不需要去 ...
随机推荐
- hdu 1575 Tr A (矩阵快速幂入门题)
题目 先上一个链接:十个利用矩阵乘法解决的经典题目 这个题目和第二个类似 由于矩阵乘法具有结合律,因此A^4 = A * A * A * A = (A*A) * (A*A) = A^2 * A^2.我 ...
- 64位SqlServer通过链接服务器与32位oracle通讯
在SQL SERVER里只安装了32位的oracle客户端的情况下,添加链接服务器然后执行查询会报如下信息: 原因:在64位的SQL Engine中已经不提供MSDAORA 的驱动了,可以使用Ora ...
- shell 的判断与比较
1 shell 的$! ,$?, $$,$@ $n $1 the first parameter,$2 the second... $# The number of co ...
- POJ 1146 ID Codes (UVA146)
// 求下一个排列// 如果已经是最后一个排列// 就输出 No Successor// stl 或 自己写个 生成排列 我测试了下 两个速率是一样的.只是代码长度不同 /* #include < ...
- 自动FTP的小脚本
自动FTP的小脚本 使用以下脚本,可以实现自动FTP,将你需要的文件传送到需要的地方,或者将需要的文件从某个地方抓取下来. cd /PATH_YOU_WANT_TO_UPLOAD(DOWNLOAD) ...
- Spring AOP (上)
工作忙,时间紧,不过事情再多,学习是必须的.记得以前的部门老大说过:“开发人员不可能一天到晚只有工作,肯定是需要自我学习.第一:为了更充实自己,保持进步状态.第二:为了提升技术,提高开发能力.第三:保 ...
- Domain Name System (DNS)
1.DNS和WINS的作用 DNS:(Domain Name Server,域名服务)用于实现域名和IP地址的相互转换. WINS:(Windows Internet Name Service) 用来 ...
- iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- Iwpriv工作流程及常用命令使用
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- POJ 1811 Prime Test
题意:对于一个大整数,判断是否质数,如果不是质数输出最小质因子. 解法:判断质数使用Miller-Rabin测试,分解质因子使用Pollard-Rho,Miller-Rabin测试用的红书模板,将测试 ...