fg313071405的专栏

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

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

首先看看

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

currentThread] description]);

FMDatabase *db = [selfdatabase];

block(db);

currentThread] description]);

if ([dbhasOpenResultSets]) {

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

}

const char *queueName = dispatch_queue_get_label(_queue);

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

});

}

这个是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放到你声明的这个方法所属的线程中去,所以上面的任务就会被放到主线程中运行。

参考:

?p=13306。

这样这个疑问解开了。

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

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

快乐要懂得分享,才能加倍的快乐

fg313071405的专栏

相关文章:

你感兴趣的文章:

标签云: