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

  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. IOS 使用FMDB多线程访问数据库 及databaseislocked的问题

    原理:文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写.在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译s ...

  7. SQLite多线程写锁文件解决方案

    在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题. 思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作:其他线程来写时,需要先检测是否有进程正在 ...

  8. 使用FMDB多线程访问数据库,及database is locked的问题

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...

  9. Sqlite多线程相关整理

    Sqlite多线程相关整理 Sqlite With MultiThreads 什么是线程安全? 当多个线程访问某个方法时,不管你通过怎样的调用方式.或者说这些线程如何交替地执行,我们在主程序中不需要去 ...

随机推荐

  1. 函数buf_read_page

    /********************************************************************//** High-level function which ...

  2. bzoj1266: [AHOI2006]上学路线route

    最短路+最小割 首先如何使最短路变长?就是要每一条最短路都割一条边. 我们求出每个点到点1和点n的距离,就可以知道哪些边在最短路上(一开始没有想到求到0和n的距离,想用floyd,但是n=500,怕超 ...

  3. 關於NPOI的一點補充和示例

    最近看到很多人分享NPOI的用法. 但是很多都不是完整示例或者並沒有實戰效果. 剛好最近有個VB.NET的項目有升級原有的oledb select sheet$的做法. 很明顯,NPOI有更好的穩定性 ...

  4. Android中shape中的属性大全

    ---恢复内容开始--- <shape> <!-- 实心 --> <solid android:color="#ff9d77"/> <!- ...

  5. apache开源项目-- Turbine

    1.缘起 Jetspeed是Apache Jakarta小组的开放源码门户系统.它使得最终用户可以通过WAP手机.浏览器.PDA等各种设备来使用各种各样的网络资源(比如应用程序.数据以及这之外的任何网 ...

  6. Android Studio进行NDK编程

  7. SQL2012远程连接到SQL2008时的问题:已成功与服务器建立连接,但在登陆过程中发生错误。

    服务器装的是2008,我机上装的是2012,结果一远程连接马上报错而且2012直接crash了.后来找到这位兄弟的帖子,http://www.cnblogs.com/liuguozhu2015/p/3 ...

  8. 怎样在 Ubuntu 中修改默认程序

    导读 作为一个新手,你需要知道如何在 Ubuntu 中修改任何默认程序,这也是我今天在这篇指南中所要讲的. 对于我来说,安装 VLC 多媒体播放器是安装完 Ubuntu 16.04 该做的事中最先做的 ...

  9. 【Android】以BaseAdapter做适配器的ListView及其性能优化

    适配器的Java类 package com.app.adapter; import org.json.JSONArray; import org.json.JSONObject; import and ...

  10. SQL SERVER 实现分组合并实现列数据拼接

    需求场景: SQL SERVER 中组织的数据结构是一个层级关系,现在需要抓出每个组织节点以上的全部组织信息,数据示例如下: ADOrg_ID--------------ParentID------- ...