FMDB 引起的gcd dispatch_sync

理解FMDBDatabaseQueue与多线程操作的同步问题
本文深入探讨了FMDBDatabaseQueue在处理多线程操作时的同步机制,揭示了部分同步可能导致的问题,并通过解析源代码解释了原因。同时,文章还提供了如何避免此类问题的方法。

名字有点奇怪,主要想描述这个现象的产生过程。


问题是这样的,APP的数据库作了部分同步,当然不是用FMDBDataBaseQuque来做的,用的是synchronized,如果全部用这个没问题,但是只对读和写做了,有一部分的查询没有做同步,所以大部分的测试没出问题,线上用户表现出来的数据就出问题(这里赞一下我们的server同事,之前和他说了可能有这个问题,他就帮忙一直检测着)。这次的版本发现这个问题比较严重,所以提上日程查找原因。查出的原因就是部分同步引起的多线程操作问题。部分可能引起APP的crash。

首先看看

- (void)inDatabase:(void (^)(FMDatabase *db))block {

    FMDBRetain(self);

    

    dispatch_sync(_queue, ^() {

        NSLog(@"create_queue thread %@",        [[NSThread currentThread] description]);

        FMDatabase *db = [self database];

        block(db);

        NSLog(@"create_queue thread222 %@",        [[NSThread currentThread] description]);

        if ([db hasOpenResultSets]) {

            NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");

        }

     const  char *queueName = dispatch_queue_get_label(_queue);

        NSLog(@"queueName %@",[NSString stringWithUTF8String:queueName]);

    });

    

    FMDBRelease(self);

}

这个是FMDBDataBaseQueue 添加到队列中的实现,期初认为 dispatch_sync,既然要等待线block执行完毕,那就必须等待queue里面的这个block执行完毕,而这个queue是串行的,那么这次提交的block还不知道什么时候处理,所以更有可能堵塞了这块操作。反之这个queue如果是global的,那里面的job是并行的,那这个job是在那个线程执行的,所以log看下,结果是不论怎么样都是在thread1执行即mainthread,诡异啊。查了下资料有一种言论说编译器会优化,觉得很不可靠。最后查到官方的说法

As an optimization, this function invokes the block on the current thread when possible.
—Grand Central Dispatch (GCD) Reference

上面的this function指的就是就是dispatch_sync这个方法,所以我们要知道这个原则,就是当你在方法中使用同步分配时,GCD就会把这个task放到你声明的这个方法所属的线程中去,所以上面的任务就会被放到主线程中运行。

参考:http://www.xcoder.cn/html/mobile/iOS/2013/0508/5913.html

http://arc10.riaos.com/?p=13306。

这样这个疑问解开了。

所以在使用FMDBDataBaseQueue的时候,他的执行不是异步的,队列里面也是同步的,所以操作结果是同步返回的。如果你想异步可以参考上面的2篇文章。


另外注意dispatch_sync不能在当前的queue提交任务。这样会造成死锁。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值