日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發(fā)布時間:2025/7/14 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CoreData和SQLite多线程访问时的线程安全问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

數(shù)據(jù)庫讀取操作一般都是多線程訪問的。在對數(shù)據(jù)進行讀取時,我們要保證其當前狀態(tài)不能被修改,即讀取時加鎖,否則就會出現(xiàn)數(shù)據(jù)錯誤混亂。
IOS中常用的兩種數(shù)據(jù)持久化存儲方式:CoreData和SQLite,兩者都需要設置線程安全,在這里以FMDB來解釋對SQLite的線程安全訪問。

?

一:FMDB的線程安全:(以讀取圖片為例)

1.沒有線程安全的執(zhí)行方式:

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 //************** 數(shù)據(jù)庫保存圖片? ******************// ?FMDatabase *database = [FMDatabase databaseWithPath:[self?getDatabasePath]]; ?//打開數(shù)據(jù)庫 ?[database open]; ?NSString?*sql = @"create table if not exists Test (id integer primary key autoincrement,name text,image blob);"; ?//創(chuàng)建表 ?[database executeUpdate:sql]; ?//把UIImage對象轉(zhuǎn)化為NSData ?NSData?*data = UIImagePNGRepresentation([UIImage imageNamed:@"user_browse"]);??? ?//寫入數(shù)據(jù) ?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 //************** 數(shù)據(jù)庫線程安全 ***********// ????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);"; ????????//創(chuàng)建表 ????????[database executeUpdate:sql]; ????}]; ????//插入數(shù)據(jù) ????[queue inDatabase:^(FMDatabase *db) { ????????//寫入數(shù)據(jù) ????????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的實現(xiàn):
在當使用FMDBDatabaseQueue創(chuàng)建數(shù)據(jù)庫時,會使用GCD創(chuàng)建一個線程隊列:

1 2 3 4 5 。。。 ?_queue = dispatch_queue_create([[NSString?stringWithFormat:@"fmdb.%@",?self] UTF8String],?NULL); ????????dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge?void?*)self,?NULL); ????????_openFlags = openFlags; 。。。

  然后在讀取時調(diào)用[queue inDatabase:^(FMDatabase *db)方法,在block中會鎖定當前數(shù)據(jù)庫

1 2 3 4 5 dispatch_sync(_queue, ^() { ????????FMDatabase *db = [self?database]; ????????block(db); ????…… }

  我們可以看到實際上這里是對整個數(shù)據(jù)庫進行加鎖,以此來保證線程安全的。

?

二、CoreData的線程安全

1.沒有線程安全的coredata數(shù)據(jù)讀取:

NSManagedObjectContext對象的創(chuàng)建:_managedObjectContext = [[NSManagedObjectContext alloc] init];

插入數(shù)據(jù)操作:(AppDetailModal為數(shù)據(jù)模型)

context 為返回的 _managedObjectContext

1 AppDetailModal *newapp = [NSEntityDescription?insertNewObjectForEntityForName:TableName inManagedObjectContext:context];

其他查詢、更新、刪除操作
//獲取Entity

1 NSEntityDescription?*entity = [NSEntityDescription?entityForName:TableName inManagedObjectContext:context];

  

2.線程安全的coreData操作:

首先創(chuàng)建并行的NSManagedObjectContext對象

1 NSManagedObjectContext* context=[[NSManagedObjectContext?alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

  

1 2 3 4 5 然后在執(zhí)行讀取操作時使用一下兩個方法: -(void)performBlock:(void?(^)(void))block -(void)performBlockAndWait:(void?(^)(void))block

  

1 2 3 4 5 [context performBlock:^{ ????????//要執(zhí)行的讀取操作 ?}];

轉(zhuǎn)載于:https://www.cnblogs.com/graveliang/p/5818696.html

總結(jié)

以上是生活随笔為你收集整理的CoreData和SQLite多线程访问时的线程安全问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。