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 *)selfNULL);

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

        //要执行的读取操作

 }];

时间: 2024-12-21 10:13:15

CoreData和SQLite多线程访问时的线程安全问题的相关文章

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

http://www.jianshu.com/p/95db3fc4deb3 关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问. 一:FMDB的线程安全:(以读取图片为例) 1.没有线程安全的执行方式: //****

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

关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问. 一:FMDB的线程安全:(以读取图片为例) 1.没有线程安全的执行方式: //************** 数据库保存图片 ******************/

设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题

设计模式--单例模式(Java)--考虑多线程环境下的线程安全问题 一:单例模式概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例 二:单例模式的实现方式 特别注意,在多线程环境下,需要对获取对象实例的方法加对象锁(synchronized) 方式一:(懒汉式)程序执行过程中需要这个类的对象,再实例化这个类的对象 步骤: 1.定义静态私有对象 2.构造方法私有化保证在类的外部无法实例化该类的对象 3.定义对外开放的静

android Sqlite多线程访问异常解决方案

在开发Android的程序的时候sqlite数据库是经常用到的:在多线程访问数据库的时候会出现这样的异常:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteData

多线程创建方式及线程安全问题

1.创建线程方式 一:  创建线程方式一继承Thread类 public clsss MyThread extends Thread{ //重写run方法,设置线程任务 Run(){ } } main(){ new MyThread().start(); } 获取线程名称: Thread.currentThread()获取当前线程对象 Thread.currentThread().getName();获取当前线程对象的名称 二:创建线程方式-实现Runnable接口 创建线程的步骤. 1.定义类

多线程(三)-- 线程安全问题

安全解决 -- 互斥锁@synchronized(self) { //开始加锁,操作} 优:解决多线程抢夺资源产生的数据安全问题缺:消耗CPU资源多 使用前提:多条线程执行一块代码时加锁 线程同步:@synchronized()多条线程在同一条线上执行(按顺序执行,与线程并发不同) nonatomic 与 atomicatomic保护线程安全,自动加锁为setter加锁 对比atomic:线程安全,消耗大量资源nonatomic:非线程安全,适合内存小的移动设备

JAVA多线程(一)线程安全问题产生的原因

JAVA线程内存与主存间映射示意图 Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程使用的变量到主内存副本拷贝,线程对变量的所有操作(读取.赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量.不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成. 工作内存与主内存间交互操作 Java内存模型只保证操作必须按顺序执行,而没有保证必须是连续执行. 以下八种操作来完成 lock(锁定):作用于主内存的变

C# - 多线程 之 进程与线程

转自原文 C# - 多线程 之 进程与线程 目录 并行~并发 进程~多进程 线程~多线程 线程池 线程同步 线程安全 回到顶部 并行~并发 并发 Concurrency,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤序列执行.并发性是对有限物理资源强制行使多用户共享(多路复用)以提高效率. 并行 Parallelism,物理上的同时发生,多核处理器或多个处理器(在同一时刻)同时处理多个任务.并行

39、集合线程安全问题

由于Set.List和Map都是线程不安全的,为了同步控制,Collections类提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题,例如: 1 public class Test { 2 3 public static void main(String[] args) { 4 5 Collection c=Collections.synchronizedCollection(new ArrayList()