日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

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

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

?

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

1.沒有線程安全的執行方式:

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 //************** 數據庫保存圖片? ******************// ?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,使用線程隊列

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 //************** 數據庫線程安全 ***********// ????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創建一個線程隊列:

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; 。。。

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

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

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

?

二、CoreData的線程安全

1.沒有線程安全的coredata數據讀取:

NSManagedObjectContext對象的創建:_managedObjectContext = [[NSManagedObjectContext alloc] init];

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

context 為返回的 _managedObjectContext

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

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

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

  

2.線程安全的coreData操作:

首先創建并行的NSManagedObjectContext對象

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

  

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

  

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

轉載于:https://www.cnblogs.com/graveliang/p/5818696.html

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。