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

转载 2015年07月09日 11:46:31

关于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);
    ……
}

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:^{

        //要执行的读取操作

 }];


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

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

关于CoreData的多线程安全问题

CoreData中的NSManagedObjectContext在多线程中不安全,如果想要多线程访问CoreData的话,最好的方法是一个线程一个NSManagedObjectContext, ,每...
  • iOSbird
  • iOSbird
  • 2015年12月16日 14:17
  • 337

多线程_线程安全问题的产生原因分析

package cn.itcast_09; /* * 如何解决线程安全问题呢? * * 要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否有线程安全问题的...

java多线程学习之通过synchronized加锁解决线程安全问题

商品类package learn.thread;public class Commodity { public static int cNum = 5; // 购买并返回剩余数 ...

多线程-02,线程安全问题解决

同步代码块: 代码: /** * 运行出现 打印出0,-1,-2错票 * 线程出现了安全问题 * * 问题原因:当多条语句操作‘同一个’线程共享数据时,一个线程对多条语句只执行了一部分,还没有...

多线程(四)线程的同步之线程安全问题

关于线程安全问题,有一个经典的问题:银行取钱的问题。银行取钱的基本流程可以分为如下几个步骤: 1、用户输入账号、密码,系统判断用户的账户、密码是否匹配; 2、用户输入取款金额; 3、系统判断账户...

黑马程序员——Java多线程之线程安全问题

多线程出现问题的原因          当多条语句在操作同一个共享数据是,一个线程对多条语句执行了一部分还没有执行完成,另一个线程参与进来执行,导致共享数据的错误。          例如在上一篇博客...

iOS多线程全套:线程安全问题,GCD的使用,NSOperation的使用

目的本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述。 多线程的基本概念 线程的状态与生命周期 多线程的四种解决方案:pthread,NSThre...

java 多线程学习之多生产者多消费者产生的线程安全问题分析与解决:Lock和Condition

//多生产者多消费者 //这是一段会产生错误数据的示例class Resource { private String name; int count; boolean flag...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于CoreData和SQLite多线程访问时的线程安全问题
举报原因:
原因补充:

(最多只允许输入30个字)