话不多说,先上代码,在分析

Code

- (void)viewDidLoad {
[super viewDidLoad]; dispatch_group_t group1 = dispatch_group_create();
dispatch_group_t group2 = dispatch_group_create(); NSLog(@"1,begin");
if (1)
{
[self func1WithGroup:group1];
dispatch_group_enter(group2);
dispatch_group_notify(group1, dispatch_get_global_queue(0, 0), ^{
NSLog(@"6, after group1 clear");
[self func2WithGroup:group2];
dispatch_group_leave(group2);
});
} //如果if中是0,那么也会执行,不会阻塞
//因为group对应的值是0
dispatch_group_notify(group2, dispatch_get_global_queue(0, 0), ^{
NSLog(@"9, after group2 clear");
[self finalFunc:group2];
});
NSLog(@"not blocking code ");
} - (void)func1WithGroup:(dispatch_group_t)group
{
dispatch_group_enter(group);
NSLog(@"2,after group1 enter");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"3,before group1 leave");
[NSThread sleepForTimeInterval:1];
dispatch_group_leave(group);
NSLog(@"5, after group1 leave"); });
} - (void)func2WithGroup:(dispatch_group_t)group
{
dispatch_group_enter(group);
NSLog(@"7,after group2 enter");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:1];
dispatch_group_leave(group);
NSLog(@"8, after group2 leave");
}); } - (void)finalFunc:(dispatch_group_t)group
{
NSLog(@"%@",NSStringFromSelector(_cmd));
}

输出如下

 1,begin
2,after group1 enter
not blocking code
3,before group1 leave
5, after group1 leave
6, after group1 clear
7,after group2 enter
8, after group2 leave
9, after group2 clear
finalFunc:

先熟悉几个概念

dispatch group 是 GCD 的一项特性,能够把任务分组。调用者可以等待这组任务执行完毕,也可以在提供回调函数之后继续往下执行,这组任务完成时,调用者会得到通知。

此外还有两个函数 dispatch_group_enterdispatch_group_leave

前者能够使分组里正要执行的任务数递增,而后者则使之递减。

dispatch_group_notify 这个函数,可以向此函数传入 block,等待 group 中任务数完成后,block 会在响应的队列中执行。

假如当前线程不应阻塞,而开发者又想在那些任务全部完成时得到通知,那么此做法就很有必要了。

代码分析

  1. 首先打印了 1,begin
  2. 同步调用了 func1WithGroup,打印了 2,after group1 enter
  3. 所有的函数都不是阻塞的,所有打印了not blocking code
  4. func1WithGroup 中全局队列得到调用,打印了3,before group1 leave5, after group1 leave
  5. 由于此前 group1 中任务数都不是 0,所以第一个 dispatch_group_notify 对应的 block 一直没有被调用。此时 group1 中任务被清空,此 block 被调用,打印了 6, after group1 clear
  6. block 中调用了 func2WithGroup,打印了 7,after group2 enter
  7. func2WithGroup 中 block 被调用,打印了 8, after group2 leave
  8. 由于调用了 dispatch_group_enter,此前 group2 中任务数目不是 0。此时被清空,group2 对应的 block 被调用,打印 9, after group2 clear
  9. 调用 finalFunc,打印方法名字 finalFunc

思考

  1. 利用 dispatch group 可以实现同步,也很方便把原来耗时操作放在异步线程中而不影响函数的调用时序,比如可以把全局队列的休眠函数换为文件读写。
  2. dispatch_group_enterdispatch_group_leave 要配对

参考

  • Matt Galloway, 爱飞翔. Effective Objective-C 2.0:编写高质量iOS与OS X代码的52个有效方法[J]. 中国科技信息, 2014(6):131-131.

GCD 中使用 dispatch group 进行同步操作的更多相关文章

  1. 深入ObjC GCD中的dispatch group工作原理。

    本文是基于GCD的支持库libdispatch的源代码分析的结果或是用于作为源代码阅读的参考,尽量不帖代码,力求用UML图来说明工作流. 本文参考的源代码版本为v501.20.1,如有兴趣请自行到苹果 ...

  2. Swift中的GCD——常见的dispatch方法

    什么是GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法.该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中.GCD ...

  3. GCD中的dispatch_group函数的详解

    <一>引入dispatch_group函数的目的 在追加到dispatch_Queue中的多个处理全部结束后想要执行结束的处理,这种需求经常会在我们的程序中出现 (第一种情况)只使用一个S ...

  4. GCD中的dispatch_apply的用法及作用

    GCD中的dispatch_apply的用法及作用 (一)dispatch_apply的基本用法 dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联A ...

  5. iOS开发-多线程之GCD(Grand Central Dispatch)

    Grand Central Dispatch(GCD)是一个强有力的方式取执行多线程任务,不管你在回调的时候是异步或者同步的,可以优化应用程序支持多核心处理器和其他的对称多处理系统的系统.开发使用的过 ...

  6. GCD中使用dispatch_after函数延迟处理任务

    在实际的开发中,经常会遇到想要在指定的时间间隔后执行某个处理 <一>在GCD中提供了dispatch_after函数来完成这一操作 dispatch_after(dispatch_time ...

  7. GCD (Grand Central Dispatch) 笔记

    GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开 ...

  8. iOS 关于GCD中的队列

    GCD中队列分类及获得方式 1.串行队列  dispatch_queue_t queue = dispatch_queue_create("队列名", DISPATCH_QUEUE ...

  9. MySQL中distinct和group by性能比较[转]

    MySQL中distinct和group by性能比较[转] 之前看了网上的一些测试,感觉不是很准确,今天亲自测试了一番.得出了结论(仅在个人计算机上测试,可能不全面,仅供参考) 测试过程: 准备一张 ...

随机推荐

  1. 16款值得一用的iPhone线框图模板 (PSD & Sketch)

    在任何网站或移动应用设计的过程中,线框图作为设计元素和功能的图示,它有助于帮助定义和更好地传达信息层次结构,让参与设计和开发的人员更好的理解设计师的思路和设计的功能点. 即使线框图设计是一个比较耗时的 ...

  2. 上海第八中学 shader

    http://shiba.hpe.cn/jiaoyanzu/wuli/soft/xna.aspx?classId=4

  3. 2018.10.19 NOIP模拟 加密(模拟)

    传送门 直接按hashhashhash函数反着算回去就行了. 加法用exgcdexgcdexgcd,异或直接枚举二进制位. 代码

  4. 2018.10.02 NOIP模拟 序列维护(线段树+广义欧拉定理)

    传送门 一道比较好的线段树. 考试时线性筛打错了于是弃疗. 60分暴力中有20分的快速幂乘爆了于是最后40分滚粗. 正解并不难想. 每次区间加打懒标记就行了. 区间查询要用到广义欧拉定理. 我们会发现 ...

  5. hdu-1728(bfs+优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1728 注意:1.先输入起点(y1,x1)和终点(y2,x2): 2.如果一个一个遍历会超时. 思路:每 ...

  6. PHP中的mb_convert_encoding与iconv函数介绍

    php传输乱码 mb_convert_encoding这个函数是用来转换编码的.原来一直对程序编码这一概念不理解,不过现在好像有点开窍了. 不过英文一般不会存在编码问题,只有中文数据才会有这个问题.比 ...

  7. java代码中存在的Big Endian 和 Little Endian

    Big Endian 和 Little Endian 详解 Java中的Big(Little)-endian问题的一种解决方法 主机序和网络序  很重要很重要 几种ip存放形式 Big-Endian和 ...

  8. hdu4417(Super Mario)—— 二分+划分树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. cried me a river--kristinia debarge

    cried me a river--kristinia debarge I still remember the day that we metI hold on to every word you ...

  10. 团队博客-第六周:Alpha阶段项目复审(科利尔拉弗队)

    团队的排名-点评:以下排名点评谨代表个人观点,如有冒犯,评论联系删除 小组名字和链接 优点 缺点,bug报告(至少140字) 最终名次(无并列) 中午吃啥队 微信小程序应用,新型app会是一个便利的使 ...