iOS 杂谈iOS 系列多线程

dispatch_sync 的分析

2016-08-30  本文已影响855人  酸菜Amour

dispatch_sync 函数同步任务处理函数,这里我将根据几种常见的情况来分析这个函数的运作机制,这几种情况分别是:

1.在主线程中将同步任务压进主队列中(死锁):

dispatch_sync 在 libdispatch 是 封装成 dispatch_sync_f 的:

dispatch_sync_f

里面有个 slowpatch(x) 和 fastpatch(x) 的宏定义,其实这两个宏定义完全没什么作用,就是返回 X 。

现在分析一下,在主线程中将同步任务压进主队列会发生什么,首先主队列的宽度是1的,所以它会进入 dispatch_barrier_sync_f 函数中:

dispatch_barrier_sync_f

在 if 里面,它会判断进入的队列是否有其他任务,是否被挂起,是否能加锁,很明显,主队列中还有其他任务(我们现在执行的函数就是主队列的任务),则会进入 _dispath_barrier_sync_f_slow 函数中:

_dispath_barrier_sync_f_slow

简单说一下这个函数里面的内容,这个函数就是封装了一个信号量,然后将信号量压进队列中,然后在这个函数中等待那个信号量,如果主队列中会出现什么情况?信号量被压进主队列中,然后信号量的上一个任务刚好是这个函数,永远都执行不到信号量的函数,然后死锁就愉快的发生了。

2.向一个串行队列中压进一个同步任务:

在上面的分析,会跑到 dispatch_barrier_sync_f ,因为这个串行队列是刚创建的,里面不可能有其他任务,所以这个任务会直接执行。

3.向一个并发队列中压进一个同步任务:

并发队列宽度大于1,在 dispatch_sync_f 函数中,会跳过 _dispath_barrier_sync_f_slow 函数,然后判断这个并发队列中是否存在其他任。

(1).如果不存在其他任务,会判断这个任务是用户自创建的队列还是全局队列,如果是用户自己创建的队列,直接执行任务,如果是全局队列,则唤醒这个队列,进入 _dispatch_sync_f_slow 函数,这里简单说一下这个函数,这个函数是会将信号量压进它的形参队列中,然后等待这个信号量,所以如果这是个全局队列,则很快等待这个信号量(在其他线程会释放这个信号量,表明这个全局队列的线程开启成功),然后直接执行任务;

(2).如果队列中存在其他任务,则直接进入 _dispatch_sync_f_slow 函数,等待这个队列中的其他任务完成(信号量的方式),然后执行这个任务。

我们从上可以看出,我们执行同步任务的时候,从来都没有压进队列中,不需要经过其他方式的调度,直接在 dispatch_sync_f 函数中运行任务的。

上一篇下一篇

猜你喜欢

热点阅读