GCD全解-11-GCD死锁

GCD系列是阅读官方文件和在实践中总结的一些常见的GCD用法,基本涉及全部的GCD内容形成的集合文章,文章重点在与精简和全面覆盖。

学习本集合你可以了解:
1. GCD是如何做到多线程调度的
2. 对比其他iOS的多线程方案,GCD的优势和劣势
3. 如何使用GCD相关的API

我将在后续不断补充详细内容和实际案例, 欢迎关注,提问和讨论

01-dispatch-iOS系统调度

02-dispatch_queue-调度队列

03-dispatch_after/dispatch_time-延迟调度和操作

04-dispatch_barrier_sync/async-线程阻塞

05-dispatch_apply-重复提交操作

06-dispatch_once-单次执行

07-dispatch_semaphore-信号量/数据同步

08-dispatch_group-调度组/多异步操作控制

09-dispatch_block-GCD取消操作

10-dispatch_source-调度资源

11-GCD死锁

dispatch_sync将block转换后检查队列宽度为1,调用dispatch_barrier_sync_f
void dispatch_sync(dispatch_queue_t dq, void (^work)(void))
{
    struct Block_basic *bb = (void *)work;
    dispatch_sync_f(dq, work, (dispatch_function_t)bb -> Block_invoke);
}

void dispatch_sync_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func){
    typeof(dq->dq_running) prev_cnt;
    dispatch_queue_t old_dq;

    if (dq->dq_width == 1) { 主队列满足条件
        return dispatch_barrier_sync_f(dq, ctxt, func);
    }
    …..
}

void dispatch_barrier_sync_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func) {
    dispatch_queue_t old_dq = _dispatch_thread_getspecific(dispatch_queue_key);

    // 1) ensure that this thread hasn't enqueued anything ahead of this call 检查队列是否在尾部
    // 2) the queue is not suspended 队列是否暂停挂起
    // 3) the queue is not weird 队列是否能被正常加锁
    if (slowpath(dq->dq_items_tail) 成立
        || slowpath(DISPATCH_OBJECT_SUSPENDED(dq))
        || slowpath(!_dispatch_queue_trylock(dq))) {
        return _dispatch_barrier_sync_f_slow(dq, ctxt, func);
    }
}
满足条件就会使用mutex(互斥锁)后去当前进程资源锁,执行block代码块.
然后释放锁整个调用结束; 由于线程阻塞的时候, 队列并不在尾部, 
不满足条件就会跳入到_dispatch_barrier_sync_f_slow
static void _dispatch_barrier_sync_f_slow(dispatch_queue_t dq, void *ctxt, dispatch_function_t func) {
  ……. 一堆……
//---------------重点是这里---------------
使用_dispatch_queue_push将我们的block压入main queue的FIFO队列中
_dispatch_queue_push(dq, (void *)&dbss);
dispatch_semaphore_wait(dbss2.dbss2_sema, DISPATCH_TIME_FOREVER);然后等待信号量,ready后被唤醒。
_dispatch_put_thread_semaphore(dbss2.dbss2_sema);然后dispatch_semaphore_wait返回_dispatch_semaphore_wait_slow(dsema, timeout)函数,持续轮训并等待,直到条件满足
}
…………

所以在此过程中,我们最初调用的dispatch_sync函数一直得不到返回,main queue被阻塞,而我们的block又需要等待main queue来执行它。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值