关于CoreData和SQLite多线程访问时的线程安全问题
关于CoreData和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,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,300)]; imageView.image = [UIImage imageWithData:imageData]; [self.view addSubview:imageView]; } }];
分析一下线程安全下的FMDB的实现: 。。。
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@",self] UTF8String],NULL);
dispatch_queue_set_specific(_queue,kDispatchQueueSpecificKey,(__bridge void *)self,NULL);
_openFlags = openFlags;
。。。
然后在读取时调用 dispatch_sync(_queue,^() {
FMDatabase *db = [self database];
block(db);
……
}
我们可以看到实际上这里是对整个数据库进行加锁,以此来保证线程安全的。 二、CoreData的线程安全1.没有线程安全的coredata数据读取: NSManagedObjectContext对象的创建: 插入数据操作:(AppDetailModal为数据模型) context 为返回的 _managedObjectContext AppDetailModal *newapp = [NSEntityDescription insertNewObjectForEntityForName:TableName inManagedObjectContext:context];
其他查询、更新、删除操作 NSEntityDescription *entity = [NSEntityDescription entityForName:TableName inManagedObjectContext:context];
2.线程安全的coreData操作: 首先创建并行的NSManagedObjectContext对象 NSManagedObjectContext* context=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
然后在执行读取操作时使用一下两个方法:
[context performBlock:^{ //要执行的读取操作 }]; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |