CoreData和SQLite多线程访问时的线程安全问题
数据库读取操作一般都是多线程访问的。在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱。
IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问。
一:FMDB的线程安全:(以读取图片为例)
1.没有线程安全的执行方式:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
//************** 数据库保存图片 ******************// 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,使用线程队列
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
//************** 数据库线程安全 ***********// 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创建一个线程队列:
|
1
2
3
4
5
|
。。。 _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中会锁定当前数据库
|
1
2
3
4
5
|
dispatch_sync(_queue, ^() { FMDatabase *db = [self database]; block(db); ……} |
我们可以看到实际上这里是对整个数据库进行加锁,以此来保证线程安全的。
二、CoreData的线程安全
1.没有线程安全的coredata数据读取:
NSManagedObjectContext对象的创建:_managedObjectContext = [[NSManagedObjectContext alloc] init];
插入数据操作:(AppDetailModal为数据模型)
context 为返回的 _managedObjectContext
|
1
|
AppDetailModal *newapp = [NSEntityDescription insertNewObjectForEntityForName:TableName inManagedObjectContext:context]; |
其他查询、更新、删除操作
//获取Entity
|
1
|
NSEntityDescription *entity = [NSEntityDescription entityForName:TableName inManagedObjectContext:context]; |
2.线程安全的coreData操作:
首先创建并行的NSManagedObjectContext对象
|
1
|
NSManagedObjectContext* context=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; |
|
1
2
3
4
5
|
然后在执行读取操作时使用一下两个方法:-(void)performBlock:(void (^)(void))block-(void)performBlockAndWait:(void (^)(void))block |
|
1
2
3
4
5
|
[context performBlock:^{ //要执行的读取操作 }]; |
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,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤 ...
- Java中类的线程安全问题
java中各种集合(字符串类)的线程安全性!!! 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读 ...
- 逐步理解Java中的线程安全问题
什么是Java的线程安全问题? 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读/写完,其他线程才可使用.不会出现数据不一致或者数据 ...
- (转)java线程安全问题之静态变量、实例变量、局部变量
java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...
- Scala中的IO操作及ArrayBuffer线程安全问题
通过Scala对文件进行读写操作在实际业务中应用也比较多,这里介绍几种常用的方式,直接上代码: 1. 从文件中读取内容 object Main { def loadData(): Array[Stri ...
随机推荐
- 转:Java IO流学习总结
Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...
- 【Alpha】阶段 第六次 Scrum Meeting
每日任务 1.本次会议为第 六次 Meeting会议: 2.本次会议在上午09:35,大课间休息时间在陆大召开,召开本次会议为20分钟,讨论统一下时间安排的问题以及一些程序上的该进: 一.今日站立式会 ...
- 201521123083《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 2. 书面作业 1. 代码阅读:Child压缩包内源代码 1.1 com.par ...
- C++学习笔记——STL(标准模板库)
1.首先.需要学习C++ 模板的概念 2.C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表. ...
- 201521123009 《Java程序设计》第12周学习总结
1. 本周学习总结 2. 书面作业 Q1:将Student对象(属性:int id, String name,int age,double grade)写入文件student.data.从文件读出显示 ...
- 201521123068 《java程序设计》 第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1.MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己 ...
- 纳税服务系统【异常处理、抽取BaseAction】
前言 本博文主要讲解在项目中异常是怎么处理的.一般我们都不会直接把后台异常信息返回给用户,用户是看不懂的.让用户看见一大串的错误代码,这是不合理的.因此我们需要对报错进行处理. 我们在开发的时候是使用 ...
- TestNG操作详解
运行测试步骤方法有如下两种: 1. 直接在Eclipse运行testNG的测试用例, 在代码编辑区域鼠标右键, 选择Run as ->testNG Test 2. 在工程的根目录下, 建立tes ...
- 字符、字符集、编码,以及它们python中会遇到的一些问题(下)
在看了很多的博客文章之后,总结整理得到了以下文章,非常感谢这些无私奉献的博主! 文章末尾有本文引用的文章的链接,如果有漏掉的文章引用,可以发邮件联系我,随后再次附上链接! 侵删!!! 这一部分是下篇, ...
- 快速学会require的使用
快速学会使用require.js 1.get start 先到官网下载requirejs到本地,官方同时提供Node版本r.js,我们只使用requirejs即可. 接下来在页面上写入 <scr ...