美文网首页lockthread
iOS中关于dispatch_semaphore_t信号量的一些

iOS中关于dispatch_semaphore_t信号量的一些

作者: 小冰山口 | 来源:发表于2018-11-03 00:49 被阅读0次

本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

最近看到一篇关于信号量的文章:

AFNetWorking与dispatch_semaphore_t能共存吗

答案是不能!

作者本来给出了解释, 无奈原答案删除了, 我试着解答一波

原文图片1

先说结论: 发生了死锁!

  • 原因: AFN框架已经把successfailure的回调放在了主线程中. 所以程序在走到dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOEVER)这句代码的时候, 已经将主线程锁住了, 所以同处于主线程的successfailure的回调block压根就不会走, 所以同时放在主线程中的dispatch_semaphore_signal(semaphore)同样也不会走, 那么信号量的
    value值也不可能增大, 所以value值一直为0, 那么被锁住的主线程就永远锁住了.

但是如果使用苹果的NSURLSession的话, 就不会死锁!

原文图片2
  • 原因: 苹果原生的completionHandler回调并没有放在主线程中, 所以当主线程处于等待状态中时, completionHandler依然在异步执行, 当执行完毕时, semaphorevalue+1, 那么被锁住的线程就被唤醒, 就会继续执行下面的代码, 而不会发生死锁!

其实整个下来就三四个方法:

  • dispatch_semaphore_t dispatch_semaphore_create(long value);

这个方法就是利用给定的value值创建一个计数信号
信号值必须是>=0的整数
当不再使用信号时, 必须调用dispatch_release来释放semaphore对象

  • long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);

这个方法首先将semaphore对象的信号值-1, 当semaphore对象的信号值<0时, 当前线程锁住(处于休眠状态), 休眠的时间由timeout参数决定.
DISPATCH_TIME_FOREVER这个宏表示无限期休眠.

  • long dispatch_semaphore_signal(dispatch_semaphore_t dsema)

这个方法首先将semaphore对象的信号值+1, 当semaphore对象的信号值>=0时, 当前线程被唤醒, 得以继续执行队列中的其他任务.

那我们再回到图2的代码:

这段代码中有2个线程: 主线程和session回调方法所处的子线程.
当子线程中拿不到回调数据的话, 主线程将会一直处于休眠状态.
所以当这段代码中dispatch_semaphore_wait以下的代码开始执行时, 一定是拿到session的回调数据了的.

信号量的方法通常用来管理线程池,
但是一定要注意semaphorevalue值的平衡, 调用了dispatch_semaphore_signal方法, 就需要再某处调用dispatch_semaphore_wait方法, 这有点类似于管理OC对象的引用计数.
但是使用不好也会有诸多不便, 比如由于处理不当, 经常出现主线程死锁的情况. 这样就得不偿失了.

PS. 本人有若干成套学习视频, 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

相关文章

网友评论

    本文标题:iOS中关于dispatch_semaphore_t信号量的一些

    本文链接:https://www.haomeiwen.com/subject/ztvhxqtx.html