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

前端之家收集整理的这篇文章主要介绍了关于CoreData和SQLite多线程访问时的线程安全问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

关于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,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,image blob);";

        //创建表

        [database executeUpdate:sql];

    }];

    //插入数据

    [queue inDatabase:^(FMDatabase *db) {

        //写入数据

        sql = @"insert into Test (name,?)";

        [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,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]; 

然后在执行读取操作时使用一下两个方法

    @H_301_71@

    -(void)performBlock:(void (^)(void))block

    @H_301_71@

    -(void)performBlockAndWait:(void (^)(void))block

[context performBlock:^{

        //要执行的读取操作

 }];
原文链接:https://www.f2er.com/sqlite/199499.html

猜你在找的Sqlite相关文章