GCD 探究
多线程业务处理是一种提高效率,优化体验的通用做法, iOS 中常常使用的其中之一就是 GCD , 其中一个比较有意思的 dispatch_barrier 最容易让人迷惑...
dispatch_barrier
应用场景: 并发队列中,存在顺序问题, 某个任务执行完成后才能执行其余操作.
易错点: dispatch_barrier_asyn
与 dispatch_barrier_sync
的区别
这里首先要明白两个概念:
- 同步与异步的区别
- 同步: 阻塞 当前线程, 必须要将任务代码执行完成后,才能返回.
- 同步一定不会开子线程
- 异步: 不阻塞 当前线程, 提交任务后, 直接返回, 任务何时执行,不关心
- 同步: 阻塞 当前线程, 必须要将任务代码执行完成后,才能返回.
- 队列 : 数据结构的一种, 遵循先进先出
FIFO
的原则- 队列是 管理任务 , 而不是线程!!!
- 并发队列: 队列中的元素为 一个一个的任务, 任务执行需要耗时, 并发的概念是 任务是按照添加的顺序来从队列中拿出来, 给对应的线程来执行, 关键点是, 并发的队列不会等待任务执行完成就可以取出下一个任务元素.
- 开始执行 是有顺序,结束执行没有顺序. 当然这个开始执行并不是说执行代码,仅仅是说将任务从队列中拿出来, 给相应的线程, 可能后出来的任务创建线程快,也说不定.
- 串行队列与并发队列的特性.
- 异步不一定会开启子线程, 串行队列,任务仍然是当前线程来处理, 并发队列则会开启子线程 - 容易混淆: 任务提交队列的顺序 与 任务从队列中出列,并执行的顺序
dispatch_barrier_asyn
dispatch_barrier_asyn
只能配合dispatch_queue_create
创建的并发队列,才能起到阻塞当前添加任务的作用, 否则就相当于一个简单的dispatch_async
dispatch_barrier_asyn
配合自建的并发队列
,任务执行特点是dispatch_barrier_asyn
之前的任务无序执行,都完成后, 再执行dispatch_barrier_asyn
提交的任务, 然后无序执行之后的添加任务.
dispatch_barrier_sync
考虑问题, 一定要明白前提条件!!!
dispatch_barrier_sync
首先要明白, 它有dispatch_sync
的特性, 也就是阻塞当前线程,它会等待当前任务执行完成!!!!, 不论当前的线程是哪种,无关队列- 如果是
dispatch_barrier_sync
提交到的队列一个串行队列或者是一个全局并发队列,效果等同dispatch_sync
; 如果是串行队列, 那就可能死锁 GG 了,注意一定是有可能,因为创建任务的队列和dispatch_barrier_sync
提交到的队列如果是不同的队列就没问题. 而创建dispatch_barrier_sync
任务的队列和dispatch_barrier_sync
任务提交到的队列是同一个队列则会死锁. 比如当前主线程创建的任务,提交到主队列 - 如果是
dispatch_barrier_sync
提交到自定义并发队列, 也就是在并发队列屁股后面添加了一个任务,那么等到并发队列出列到dispatch_barrier_sync
提交的任务后, 该任务不会执行, 而是会等待已经出列的任务,全部执行完成后,才会执行, 并且阻塞当前线程.
总结: 自定义的并发队列, 使用
dispatch_barrier_sync
与dispatch_barrier_asyn
区别只是在 对当前线程的影响中, 对于并发队列中的任务执行顺序是没有影响的,但是因为dispatch_barrier_sync
会阻塞当前线程, 所以在dispatch_barrier_sync
执行任务的时候, 后续的任务是没有提交到队列的, 而dispatch_barrier_asyn
在执行任务的时候, 因为不阻塞当前线程, 所以其他任务可以正常提交, 只是不能在dispatch_barrier_asyn
的任务执行完之前执行而已!!!
Discussion