FMDatabaseQueue为何会线程安全的一点心得

操作数据库时,如果是有多个并发线程同时使用到了同一个数据库,就有可能发生同时操作的可能,这个时候数据会崩溃。FMDB 给我们提供了FMDatabaseQueue 这样一种解决方法。

自己用GCD 的demo 测试后,可以初步确定,FMDatabaseQueue 能做到线程安全是 因为他使用了串行队列,即在FMDatabaseQueue.m 文件里面的这行代码:

_queue = dispatch_queue_create([[NSStringstringWithFormat:@"fmdb.%@",self]UTF8String],NULL);

关于dispatch_queue_create 的第二个参数其实是有两种的,即为:

         串形队列 DISPATCH_QUEUE_SERIAL

         并行队列 DISPATCH_QUEUE_CONCURRENT

而 DISPATCH_QUEUE_SERIAL其实是 NULL 的宏,所以说FMDatabaseQueue创建了一个串行队列,这个串行队列有什么特性而使得数据库操作可以安全进行而不会并发执行呢?

下面我会用GCD的代码进行测试,这里我先说一下结论:假设有三个GCD并发线程,在这三个线程里面执行串行线程。那么,虽然这三个线程会像并发线程一样无序执行(无序是因为这三个串行线程是在三个并发线程里面生成的,自然是并发线程无序执行后再生成此串行线程),但是却并不会并发执行,而按顺序一个串行线程执行完毕才到下一个串行线程,因此保证了数据库不会被并发执行而崩溃。


以下为测试代码:

- (void)doSomething:(NSString *)str
{
    [NSThreadsleepForTimeInterval:1.0];
    NSLog(@"====%@====",str);
}

- (void)viewDidLoad
{
        _globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
        _seriQueue =dispatch_queue_create("myQueueSerial",DISPATCH_QUEUE_SERIAL);
     [self methodTwo];
}
- (void)methodTwo
{
    dispatch_async(_globalQueue, ^{
        NSLog(@"11%@",[NSThreadcurrentThread]);
        dispatch_sync(_seriQueue, ^{
            [selfdoSomething:@"A"];
            NSLog(@"12%@",[NSThreadcurrentThread]);
        });
 //       [self doSomething:@"A"];

    });
    dispatch_async(_globalQueue, ^{
        NSLog(@"21%@",[NSThreadcurrentThread]);

        dispatch_sync(_seriQueue, ^{
            NSLog(@"22%@",[NSThreadcurrentThread]);
            [selfdoSomething:@"B"];
        });
//        [self doSomething:@"B"];
    });
    dispatch_async(_globalQueue, ^{
        NSLog(@"31%@",[NSThreadcurrentThread]);
        dispatch_sync(_seriQueue, ^{
            NSLog(@"32%@",[NSThreadcurrentThread]);
            [selfdoSomething:@"C"];
        });
     //   [self doSomething:@"C"];
    });
}


运行的结果如下:

15:16:19.763 GCDDemo[21028:897286] 11<NSThread: 0x7fa4a0774ee0>{number = 2, name = (null)}

15:16:19.763 GCDDemo[21028:897288] 31<NSThread: 0x7fa4a070a330>{number = 4, name = (null)}

15:16:19.762 GCDDemo[21028:897287] 21<NSThread: 0x7fa4a052b700>{number = 3, name = (null)}

15:16:20.765 GCDDemo[21028:897286] ====A====

15:16:20.765 GCDDemo[21028:897286] 12<NSThread: 0x7fa4a0774ee0>{number = 2, name = (null)}

15:16:20.766 GCDDemo[21028:897288] 32<NSThread: 0x7fa4a070a330>{number = 4, name = (null)}

15:16:21.767 GCDDemo[21028:897288] ====C====

15:16:21.767 GCDDemo[21028:897287] 22<NSThread: 0x7fa4a052b700>{number = 3, name = (null)}

15:16:22.769 GCDDemo[21028:897287] ====B====


可以看出, A B C 虽然无序执行,而且也不在同一个线程上,但是他们却是串行执行的,即只有当一个任务执行完毕后(也就是一秒之后)才会执行下一个任务,所以在同一个串行队列里面去操作数据是安全的。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值