深入学习GCD之dispatch_group

2021-04-08  本文已影响0人  i爱吃土豆的猫

之前已经介绍了dispatch_semaphore的底层实现,dispatch_group的实现是基于前者的。在看源码之前,我们先看一下我们是如何应用的。假设有这么场景:有一个A耗时操作,B和C两个网络请求和一个耗时操作C当ABC都执行完成后,刷新页面。我们可以用dispatch_group实现。

dispatch_group的相关API
dispatch_group_create
dispatch_group_async
dispatch_group_async_f
dispatch_group_enter:
dispatch_group_enter将dispatch_group_t转换成dispatch_semaphore_t,并调用dispatch_semaphore_wait,原子性减1后,进入等待状态直到有信号唤醒。所以说dispatch_group_enter就是对dispatch_semaphore_wait的封装。

dispatch_group_leave

这里先说明一下enter和leave之间的关系:

dispatch_group_leave与dispatch_group_enter配对使用。当调用了dispatch_group_enter而没有调用dispatch_group_leave时,由于value不等于dsema_orig不会走到唤醒逻辑,dispatch_group_notify中的任务无法执行或者dispatch_group_wait收不到信号而卡住线程。

dispatch_group_enter必须在dispatch_group_leave之前出现。当dispatch_group_leave比dispatch_group_enter多调用了一次或者说在dispatch_group_enter之前被调用的时候,dispatch_group_leave进行原子性加1操作,相当于value为LONGMAX+1,发生数据长度溢出,变成LONG_MIN,由于value == LONG_MIN成立,程序发生crash。

dispatch_group_notify
dispatch_group_notify_f
_dispatch_group_wake
dispatch_group_wait
_dispatch_group_wait_slow
总结:

  1. dispatch_group是一个初始值为LONG_MAX的信号量,group中的任务完成是判断其value是否恢复成初始值。

  2. dispatch_group_enter和dispatch_group_leave必须成对使用并且支持嵌套。

  3. 如果dispatch_group_enter比dispatch_group_leave多,由于value不等于dsema_orig不会走到唤醒逻辑,dispatch_group_notify中的任务无法执行或者dispatch_group_wait收不到信号而卡住线程。如果是dispatch_group_leave多,则会引起崩溃。

上一篇下一篇

猜你喜欢

热点阅读