【原创】OperationQueue和GCD 不确定的奇妙关系

iOS中多线程的几种实现方式是面试的热门问题,这篇文章不是讲解这三种常用的实现方式,而是想针对另外的一个引出问题:OperationQueue和GCD的关系,做一下讨论。

奇妙的关系

一直以来,OC开发界都有着这样的说法:OperationQueue是GCD的面向对象封装。但是细心的朋友们可能会有这样的疑问:OperationQueue是iOS 2就加入的老家伙,而使用block的GCD是iOS 4才有的新成员,老技术怎么可能是新技术的封装呢?还有OperationQueue中的Operation是可以cancel的,可GCD显然没有这样的功能,为什么一个功能底层没有,而上层封装却提供了呢?
我也同样有这个疑问,所以特地上网查阅了相关的文档和讨论。苹果官方文档中有这样的描述:

Operation queues usually provide the threads used to run their operations. Operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as asynchronous or synchronous operations.

简单翻译一下:Operation Queue通常提供线程,用来执行Operation。Operation Queue使用libdispatch库(又叫GCD)来启动执行Operation。因此,不管Operation是否被指定为同步或者异步,它们总是在单独的线程上执行。

争论从来没停止过

这样看来,OperationQueue的确就是GCD的封装,而且stack overflow上很多高票回答也都提到了这件事,比如这个问题中的回答就非常有意思。

大意是说从iOS 4开始OperationQueue内部就是用GCD实现了,建议用更高级的api以便更好的抽象,就意味着多用OperationQueue而非GCD。

然后我往下又看到了票数次高的回答。

上来就直接怼了上面最高票的回答,说他在GCD之前,用OperationQueue管理并发但是效率很低,在后来换成GCD之后流畅到飞起,所以他建议多使用GCD,如果不是特殊的地方,就尽量不要用OperationQueue。

说到这里似乎有些跑题了,其实我写这篇博客的目的不是想说什么时候用GCD什么时候用OperationQueue,根据每个开发者的习惯、业务需求、性能要求不同,会有不同的选择。

关键的问题是,看到这里我心里的疑惑更多了,为什么OperationQueue和GCD的性能差距可以如此之大?如果真的是封装关系,性能差距应该不至于大到这种程度。

越辩越明

于是带着这个疑问,我就继续饶有兴趣地翻阅大家在GCD和OperationQueue之间争论的话题。无意之间我又看到了这样的争论:

问题和回答其实都不重要,我觉得最精彩的地方在评论:

das在回答中提到OperationQueue是一个big hammer(大锤子),这个问题没必要祭出大锤子来解决。

Tricertops在评论中问到:OperationQueue就是GCD队列的OC封装,为什么你说它是“大锤子”?它提供了简单的api所以我喜欢它。

das回复到:你说的不对,OperationQueue不是GCD的封装,它是一个复杂队列,依赖和优先追踪系统的实现方式与GCD完全不同。它在内部使用GCD进行一些同步(与自旋锁和互斥锁一起),但是在执行客户代码方面,它与GCD唯一的关系就是OperationQueue会在一个操作执行结束,准备下一次的时候,对全局并发队列调用一次dispatch_async()。所有这些复杂性和灵活性都是要付出性能代价,简单操作的话,OperationQueue比GCD慢1000倍。

下面的quellish也是反对加质疑了das的说法。

再下面,das仍然坚持奋战:OperationQueue不是GCD的封装,除了队列,GCD和OperationQueue没有任何等价的概念。这是因为OperationQueue API的设计比GCD早几年,如果您认为文档存在误导性,请给bugreporter.apple.com提交错误信息。。。

战火越烧越旺,直到看见了下一楼,点进去是das同(da)学(shen)的领英

不由得一句我靠 有没有。。。das是苹果公司GCD的开发者,那么上面争论的输赢和道理就不用多说了。看到这里,您是不是要回过头去看看das是如何说GCD和OperationQueue的?这下终于找到权威了,如果还不过瘾,可以点进stack overflow上das的主页,看到他更多的回答。

还有一些疑问

das不止一次地明确说到OperationQueue不是GCD的封装,为什么苹果的文档还这样写?

Operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations.

其实在上面das的回答中,已经解释了这个问题:

It uses GCD internally for some synchronization (along with spinlocks and mutexes) but in terms of execution of client code the only connection to GCD is that NSOperationQueue does a dispatch_async() to the global concurrent queue at the end to execute an operation once it is ready to do so.

文档中说用OperationQueue使用GCD来initiate the execution of their operations,其实和das说的

NSOperationQueue does a dispatch_async() to the global concurrent queue at the end to execute an operation once it is ready to do so.

应该是一回事,只不过苹果的这个文档真的是非常具有误导性,还是多亏碰巧看到das大神的活跃。

你可能感兴趣的:(【原创】OperationQueue和GCD 不确定的奇妙关系)