Hi,今天跟大家聊聊iOS开发中多线程同步的话题。说到多线程同步,各位童鞋可能立刻会想到NSLock、NSCondtion甚至OSSpinLock等等各种线程锁。但是,今天我们不谈线程锁,各位如果对Lock有兴趣,可以看看这篇文章,既然不谈线程锁,那说啥?当然是说多线程同步
线程同步不等于线程锁。要解决同步问题,首先需要了解为什么需要线程同步,线程不同步主要原因在于多个线程可能同时操作某个对象从而导致状态不一致的问题。是不是可以这么理解,如果多线程不会同一时刻访问对象就解决了同步问题。如何做到这一点?可以采用串行队列的思想,何为串行队列?可以简单理解为所有操作都必须按顺序依次执行。主线程就是串行队列,最简单的同步方式就是把同步操作放到主线程执行,然并卵,当我没说
既然不能在主线程执行,放到子线程不就OK?创建子线程的方式有很多,不累述,有兴趣的童鞋可以各显神通
GCD同步
GCD可能是创建子线程最简单的方式之一,关于GCD,这篇文章做了比较详细的介绍,不再进一步描述。既然要实现线程同步,首先需要创建串行队列
1 2 3 |
_queue = dispatch_queue_create("com.olinone.synchronize.serialQueue", NULL); dispatch_queue_t dQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); dispatch_set_target_queue(_queue, dQueue); |
然后,将所有同步事件依次加入队列中即可确保多线程同步
1 2 3 |
dispatch_async(_queue, ^{ block(); }); |
NSOperationQueue同步
通过GCD的方式即可满足绝大多数需求,但是也难免有个别特殊需求,比如操作的取消。此时,NSOperationQueue将是不错的选择
NSOperationQueue虽然是并发多线程池,但是巧妙的设计也可以让其实现串行队列的功能。当maxConcurrentOperationCount=1的时候,同一时刻只有一个NSOperation被执行,NSOperationQueue就由并发执行变成串行执行
1 2 |
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; |
实现方式与GCD一样,依次将同步操作加入到线程池中即可实现同步操作的串行执行
1 2 3 4 5 6 7 8 |
- (void)execSyncBlock:(void (^)())block { if (NSOperationQueue.currentQueue == self) { block(); } else { NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:block]; [self addOperations:@[operation] waitUntilFinished:YES]; } } |
HJSynchronizeDemo详细展示了实际使用方式。巧妙的利用串行队列可以带来意想不到的效果。除了解决多线程同步,还能够处理串行式大计算等业务,比如图片渲染,音频处理等等
Pingback: App开发日报2015-07-17 Black Hat 2015黑客大会上将公布的6个移动安全威胁 等12条 | IT青年舍
持续更新,持续来访。
大哥,要多高端的iOS开发者
呵呵,可以看看招聘信息,一般要求工作3年以上,能够独立保质的完成功能开发,其它就看你个人情况了!
阿里音乐?在成都招可以考虑。外地没兴趣。
我知道阿里在成都也有分部,但是不知道那边主要是什么部门,很可惜,阿里音乐目前在成都貌似还没有分部!
北京有分部没有啊 哈哈
阿里音乐北京有分部,但不是研发,主要是市场部门!
博主,文中都是讲的多线程同步(更像是单线程同步)相关内容,能讲下多线程异步的用武之地吗?感谢分享, http://www.jianshu.com/p/77332a3b07b5 此篇是我对线程相关概念的理解,望批评指正。
感谢你的来访,看了你的文章,对并发并行介绍很透彻,学到很多,本文主要目的在于介绍如何通过单线程实现多线程同步操作!至于多线程异步,举个例子,比如某个界面显示一张模糊图片(原图片未模糊),但是图片是不断变化的,变化时间也不确定,正常情况下,每次图片变化时都需要开个子线程异步模糊图片,模糊完回调,判断是最后变化的图片时再显示出来,但是前面模糊图片的计算此时都是多余的,此时,采用单线程方式,在添加新的模糊任务时取消前面过期的模糊任务就可以大大减少多余操作!这是多线程异步的一个例子。多多交流!
希望你的博客如这个夏天一样火热。
Pingback: ReactNative源码笔记——你知道几条? - 恰同学少年-不称