iOS经典面试题之分析GCD的dispatch_group任务执行问题

① dispatch_group 异步执行任务

  • 现有以下调度组 dispatch_group 执行多个任务,将 dispatch_group_notify 放在调度组异步执行任务,那么它们的任务执行顺序是怎么样的呢?
	dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"任务1");
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"任务2");
        dispatch_group_leave(group);
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任务3:主线程更新UI");
    });
    NSLog(@"任务4:主线程正在执行");
  • 执行程序,结果如下:
	任务4:主线程正在执行
	任务2
	任务1
	任务3:主线程更新UI
  • 分析:
    • dispatch_group 执行任务开始时, 程序由上到下执行任务1、任务2、任务3、任务4;
    • 由于任务4没有在调度组中,因此优先执行;
    • 然后有两个调度组异步执行任务1和任务2,最后再通知主线程执行任务3;
    • 由于第一个任务1中线程sleep(1),因此任务2会比任务1优先完成;
    • 最后再通知主线程执行任务3,更新UI。

② 如果将 dispatch_group_notify 移动到最前面,能否执行?执行结果是怎样的呢?

  • 代码修改如下:
	dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任务3:主线程更新UI");
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"任务1");
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"任务2");
        dispatch_group_leave(group);
    });
    NSLog(@"任务4:主线程正在执行");
  • 执行结果如下:
	任务4:主线程正在执行
	任务2
	任务3:主线程更新UI
	任务1
  • 可以看到程序能正常执行,但是只要有 enter-leave 成对匹配,notify 就会执行,不会等两个调度组都执行完毕,即只要 enter-leave 成对程序就可以执行。

③ 再加一个enter,即 enter:wait 是 3:2,能否执行 notify ?

  • 修改代码如下:
	dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"任务1");
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"任务2");
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任务3:主线程更新UI");
    });
    NSLog(@"任务4:主线程正在执行");
  • 执行结果如下:
	任务4:主线程正在执行
	任务2
	任务1
  • 可以看到,程序不能正常执行完毕,会一直等待,这是因为等待 leave 的执行,最后才会执行 notify。
  • 如果 dispatch_group_enter 比 dispatch_group_leave 多,由于 value 不等于 dsema_orig 不会走到唤醒逻辑, dispatch_group_notify 中的任务无法执行或者 dispatch_group_wait 收不到信号而卡住线程。

④ 如果是 enter:wait 是 2:3,能否执行 notify ?

  • 修改代码如下:
	dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        sleep(1);
        NSLog(@"任务1");
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"任务2");
        dispatch_group_leave(group);
    });
    dispatch_group_leave(group);
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任务3:主线程更新UI");
    });
    NSLog(@"任务4:主线程正在执行");
  • 执行程序之后,可以看到程序会延迟崩溃在任务1的 dispatch_group_leave(group),这是因为 enter-leave 没有成对匹配,dispatch_group 没有 enter 却需要 leave,导致 value 不等于 dsema_orig 不会执行唤醒逻辑。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╰つ栺尖篴夢ゞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值