数据库读取操作一般都是多线程访问的。在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱。
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 *)selfNULL);
        _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多线程访问时的线程安全问题的更多相关文章

  1. 关于CoreData和SQLite多线程访问时的线程安全问题

    数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两 ...

  2. CoreData和SQLite多线程访问时的线程安全

    关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常 ...

  3. redis是单进程数据库,多用户排队对统一数据进行访问,不存在并发访问生产的线程安全问题

    redis是单进程数据库,多用户排队对统一数据进行访问,不存在并发访问生产的线程安全问题. oracle是多进程数据库,存在并发访问的问题,必须事务加锁等方式进行处理.

  4. (原创)android Sqlite多线程访问异常解决方案

    在开发Android的程序的时候sqlite数据库是经常用到的:在多线程访问数据库的时候会出现这样的异常:java.lang.IllegalStateException: Cannot perform ...

  5. C# - 多线程 之 进程与线程

    并行~并发 并发 Concurrency,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤 ...

  6. Java中类的线程安全问题

    java中各种集合(字符串类)的线程安全性!!! 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读 ...

  7. 逐步理解Java中的线程安全问题

    什么是Java的线程安全问题? 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读/写完,其他线程才可使用.不会出现数据不一致或者数据 ...

  8. (转)java线程安全问题之静态变量、实例变量、局部变量

    java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...

  9. Scala中的IO操作及ArrayBuffer线程安全问题

    通过Scala对文件进行读写操作在实际业务中应用也比较多,这里介绍几种常用的方式,直接上代码: 1. 从文件中读取内容 object Main { def loadData(): Array[Stri ...

随机推荐

  1. MPLS VPN随堂笔记3

    跨域 ASBR之间运行MPBGP 1.配置AS内部IGP保证环回口互相可达,同时建立LDP邻居 (优先启用 mpls label rang 16 100)方便查看实验现象 2.配置PE1-PE2 PE ...

  2. 团队作业4——第一次项目冲刺(Alpha版本)2st day

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 界面 1.四个用户登录界面已经完成. 2.界面内的功能完成了一小部分. 登陆部分 1.QQ授权已经申请,还未通过. 2.通过好 ...

  3. 201521123091 《Java程序设计》第3周学习总结

    Java 第三周总结 第三周的作业. Java 第三周总结 1.本章学习总结 2.Java Q&A 1.代码阅读 2.构造函数有什么用?其编写格式是什么?如果一个类不写构造函数,它有构造函数吗 ...

  4. 团队作业6--展示博客(Alpha版本)

    1.团队成员简介和个人博客地址 团队源码仓库地址:https://git.coding.net/tuoxie/dianziwendangchachong.git吕志哲 201421123021 个人博 ...

  5. 201521123103 《Java学习笔记》 第六周学习总结

    一.本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 二.书面作业 1.clone方法 1.1 Object对象中 ...

  6. 201521123032 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...

  7. java课程设计——猜数游戏个人博客

    1.团队课程设计链接 团队博客:http://www.cnblogs.com/springbreezemiles/p/7064135.html 2.个人负责模块 猜数部分的算法及代码实现. 3.自己的 ...

  8. linux(5)--补充(管道| / 重定向> / xargs)/find 与xargs结合使用/vi,grep,sed,awk(支持正则表达式的工具程序)

    本节中正则表达式的工具程序 grep,sed和awk是重点,也是难点!!! 先补充一下一. 管道| / 重定向> / xargs 如:1. 管道和重定向的区别:具体可以见 http://www. ...

  9. String ua = request.getHeader("user-agent")---ua值为null

    最近在修改错误日志,发现总报空指针,追踪代码发现这个ua的值有时候会为null,上网查了半天也无果,按常理说ua的值不可能为null,俩小时没找到原因,只是将ua判null了一下,记录一下,如果有大虾 ...

  10. 只用一招让你Maven依赖下载速度快如闪电

    一.背景 众所周知,Maven对于依赖的管理让我们程序员感觉爽的不要不要的,但是由于这货是国外出的,所以在我们从中央仓库下载依赖的时候,速度如蜗牛一般,让人不能忍,并且这也是大多数程序员都会遇到的问题 ...