话说,今天我要向大家介绍一个小Bug,它来自当今最小清新的一款音乐产品的iOS版本:进入已下载的歌单,点击“管理歌曲”,连续且快速的删除几首歌曲,App会出现闪退现象。
问题重现并不困难,如果大侠还在使用怀旧的iPhone4及其以前的产品,那么您不用太着急忙慌,只要悠闲的删除若干首歌曲,问题必现!假若高手装备着当今最洋气最高端的手机,并且怒气满100,您只要使出必杀技------幻影夺命手:快速并反复的删除歌单,直到手机的反应开始慢于您的动作之后,App的闪退现象也会不期而遇了。
人在江湖,身不由己!抓住了Bug还不够,还需要对其进行深入分析,找到问题原因:原来,删除歌曲的操作会触发歌单下载进度的重新计算,歌单下载进度的重新计算会触发歌单容器结构的快速遍历,所以连续删除的操作与歌单下载进度的计算两个线程出现了同步问题,对一个容器结构快速遍历的同时另一个线程尝试更改它,从而引发了应用程序崩溃。
增加线程控制机制,采用OperationQueue,如果一个线程在一个operation里遍历,另一个线程要改变容器时,就取消那个遍历的operation。
iOS 和 Mac OS 传统的并发编程模型是线程,不过线程模型伸缩性不强,而且编写正确的线程代码也不容易。Mac OS 和 iOS 采取asynchronous design approach 来解决并发的问题。
引入的异步技术有两个:
Grand Central Dispatch:系统管理线程,你不需要编写线程代码。只需定义想要执行的任务,然后添加到适当的dispatch queue。Grand Central Dispatch会负责创建线程和调度你的任务。系统直接提供线程管理,比应用实现更加高效。
OperationQueue:类似于dispatch queue。你定义想要执行的任务,并添加任务Operation到OperationQueue,后者负责调度和执行这些任务。和Grand Central Dispatch一样,OperationQueue也管理了线程,同样高效。OperationQueue是Cocoa版本的并发dispatch queue,由NSOperationQueue 类实现。dispatch queue总是按先进先出的顺序执行任务,而OperationQueue在确定任务执行顺序时,还会考虑其它因素。最主要的一个因素是指定任务是否依赖于另一个任务的完成。你在定义任务时配置依赖性,从而创建复杂的任务执行顺序图。
本文来自网易实践者社区,经作者陆春红授权发布