我的上篇文章iOS中多个网络请求的同步问题总结中用到了dispatch_group来进行线程同步,对用法不是特别熟悉所以整理这篇文章来加深记忆(闲着也是闲着)

一、简单介绍下将会用到的一些东西

英语不好就不翻译官方文档了..

1、dispatch_group_async

* Submits a block to a dispatch queue and associates the block with the given
* dispatch group
//将一个block(代码块)加入到dispatch_queue_t queue中并和dispatch_group_t group相关联
void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block); 

个人理解:将代码块dispatch_block_t block放入队列dispatch_queue_t queue中执行;并和调度组dispatch_group_t group相互关联;如果提交到dispatch_queue_t queue中的block全都执行完毕会调用dispatch_group_notify并且dispatch_group_wait会停止等待;

2、dispatch_group_enter(group)、dispatch_group_leave(group)

* Calling this function indicates another block has joined the group through * a means other than dispatch_group_async(). Calls to this function must be * balanced with dispatch_group_leave(). 调用这个方法标志着一个代码块被加入了group,和dispatch_group_async功能类似;dispatch_group_enter()、dispatch_group_leave()必须成对出现 void dispatch_group_enter(dispatch_group_t group); 

个人理解:和内存管理的引用计数类似,我们可以认为group也持有一个整形变量(只是假设),当调用enter时计数加1,调用leave时计数减1,当计数为0时会调用dispatch_group_notify并且dispatch_group_wait会停止等待;

3、dispatch_group_notify

void dispatch_group_notify(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block); 

个人理解:当关联到dispatch_group_t上的dispatch_group_async任务执行完毕或者是关联在上面的dispatch_group_enter、dispatch_group_leave成对出现了。参数中的dispatch_block_t block会被提交到dispatch_queue_t queue中执行。

4、dispatch_group_wait

long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout); 

个人理解:和dispatch_group_notify功能类似(多了一个dispatch_time_t参数可以设置超时时间),在group上任务完成前,dispatch_group_wait会阻塞当前线程(所以不能放在主线程调用)一直等待;当group上任务完成,或者等待时间超过设置的超时时间会结束等待;

二、dispatch_group_async代码示例

- (void)groupSync
{dispatch_queue_t disqueue =  dispatch_queue_create("com.shidaiyinuo.NetWorkStudy", DISPATCH_QUEUE_CONCURRENT);dispatch_group_t disgroup = dispatch_group_create();dispatch_group_async(disgroup, disqueue, ^{NSLog(@"任务一完成"); }); dispatch_group_async(disgroup, disqueue, ^{ sleep(8); NSLog(@"任务二完成"); }); dispatch_group_notify(disgroup, disqueue, ^{ NSLog(@"dispatch_group_notify 执行"); }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ dispatch_group_wait(disgroup, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)); NSLog(@"dispatch_group_wait 结束"); }); } 

向group中放入两个任务(准确讲是将任务加入到了并行队列disqueue中执行,然后队列和group关联当队列上任务执行完毕时group会进行同步),第二个任务会等待8秒所以第一个任务会先完成;会先打印任务一完成再打印任务二完成,当两个任务都完成时dispatch_group_notify中的block会执行;会接着打印dispatch_group_notify 执行;dispatch_group_wait设置了超时时间为5秒所以它会在5秒后停止等待打印dispatch_group_wait 结束(任务二会等待8秒所以它会在任务二完成前打印);

测试输出结果

需要注意的:dispatch_group_wait是同步的所以不能放在主线程执行。
补充: dispatch_group会等和它关联的所有的dispatch_queue_t上的任务都执行完毕才会发出同步信号(dispathc_group_notify的代码块block会被执行,group_wati会结束等待)。也就是说一个group可以关联多个任务队列;下面给出示例:

- (void)groupSync2
{dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next1", DISPATCH_QUEUE_CONCURRENT);dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); dispatch_group_t dispatchGroup = dispatch_group_create(); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ sleep(5); NSLog(@"任务一完成"); }); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ sleep(6); NSLog(@"任务二完成"); }); dispatch_group_async(dispatchGroup, globalQueue, ^{ sleep(10); NSLog(@"任务三完成"); }); dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"notify:任务都完成了"); }); } 

上面的代码里有两个队列一个是我自己创建的并行队列dispatchQueue,另一个是系统提供的并行队列globalQueue;dispatch_group_notify会等这两个队列上的任务都执行完毕才会执行自己的代码块。

多个队列执行结果

三、dispatch_group_enter、dispatch_group_level示例

和dispatch_async相比,当我们调用n次dispatch_group_enter后再调用n次dispatch_group_level时,dispatch_group_notify和dispatch_group_wait会收到同步信号;这个特点使得它非常适合处理异步任务的同步当异步任务开始前调用dispatch_group_enter异步任务结束后调用dispatch_group_leve
下面是代码示例:

- (void)groupSync
{dispatch_group_t group = dispatch_group_create();dispatch_group_enter(group);dispatch_async(dispatch_get_global_queue(0, 0), ^{sleep(5); NSLog(@"任务一完成"); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(dispatch_get_global_queue(0, 0), ^{ sleep(8); NSLog(@"任务二完成"); dispatch_group_leave(group); }); dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{ NSLog(@"任务完成"); }); } 

示例代码中在global_queue上执行sleep任务模拟网络请求。

控制台打印结果

补充: 如果像最后一个示例那样,block里执行的是同步类型的代码那么用dispatch_group_async一样可以达到同步的效果,但是异步任务就不行了如下:

- (void)groupSync2
{dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next1", DISPATCH_QUEUE_CONCURRENT);dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); dispatch_group_t dispatchGroup = dispatch_group_create(); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ dispatch_async(globalQueue, ^{ sleep(5); NSLog(@"任务一完成"); }); }); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ dispatch_async(globalQueue, ^{ sleep(8); NSLog(@"任务二完成"); }); }); dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"notify:任务都完成了"); }); } 

如果dispatch_group_async里执行的是异步代码dispatch_group_notify会直接触发而不会等待异步任务完成,而dispatch_group_enter、和dispatch_group_leave则不会有这个问题,它们只需要在任务开始前enter结束后leave即可达到线程同步的效果。


作者:liang1991链接:https://www.jianshu.com/p/228403206664來源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

使用dispatch_group来进行线程同步相关推荐

  1. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

  2. 改善C#程序的建议6:在线程同步中使用信号量

    所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两种类型上的等待是不一样的.我们可以简单的理解为在CL ...

  3. C#线程同步的几种方法

    在网上也看过一些关于线程同步的文章,其实线程同步有好几种方法,下面我就简单的做一下归纳. 一.volatile关键字 volatile是最简单的一种同步方法,当然简单是要付出代价的.它只能在变量一级做 ...

  4. MFC 多线程及线程同步

    一.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消息机制,通常 ...

  5. java同步与死锁_Java多线程 - 线程同步与死锁

    一.线程同步 1)模拟多个用户同时从银行账户里面取钱 ● Account 类:银行账户类,里面有一些账户的基本信息,以及操作账户信息的方法 //模拟银行账户 classAccount {private ...

  6. java实现线程同步的方法_Java实现线程同步方法及原理详解

    一.概述 无论是什么语言,在多线程编程中,常常会遇到多个线同时操作程某个变量(读/写),如果读/写不同步,则会造成不符合预期的结果. 例如:线程A和线程B并发运行,都操作变量X,若线程A对变量X进行赋 ...

  7. 线程同步初解---转载

    //线程安全问题的原因其实就是:线程执行多条语句的时候出现了阻塞,然后没有执行完该线程另一线程就启动了. //解决方法就是同步代码块:synchronized(对象) //synchronized(对 ...

  8. VC++中线程同步技术分析3

    管理事件内核对象 在前面讲述线程通信时曾使用过事件内核对象来进行线程间的通信,除此之外,事件内核对象也可以通过通知操作的方式来保持线程的同步.对于前面那段使用临界区保持线程同步的代码可用事件对象的线程 ...

  9. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

最新文章

  1. layDate的使用
  2. 禁止北京地区IP访问站点
  3. C语言用位运算构建特定的二进制数
  4. 在Ajax程序中实现无刷新换肤功能(asp.net2.0)
  5. react学习(68)--ant design inputNumber
  6. 爬取B站免费视频--python代码赶快拿
  7. 三月数据库技术通讯.pdf | Oracle配置DCD避免会话被防火墙强制断开
  8. java限制金额控制_JavaMail 限额管理
  9. R语言中GCC编译的问题(续)
  10. 【NumPy基础】100道numpy练习——初学与入门篇
  11. 《Adobe Premiere Pro CC经典教程(彩色版)》——第2课 设置项目 2.1 开始
  12. HybridPose:混合表示下的6D对象姿态估计
  13. 连接共享打印机0x0000011b win10
  14. OceanBase 安装-采用OCP安装
  15. css cursor 鼠标指针样式总结
  16. 前列腺增生症的治疗行业调研报告 - 市场现状分析与发展前景预测
  17. 机械振动信号 常见时域、频域特征提取 Python 代码
  18. 凯捷面试(1):JavaSE、MySQL数据库、前端
  19. Rstudio如何安装、加载工具包
  20. 算法初步 计算机程序,算法初步-程序框图

热门文章

  1. 阿里达摩院 AI医疗 「铸剑」四年:上线170家医院,落地57座城市
  2. 滴滴自动驾驶获得江苏省苏州公安局颁发的路测牌照
  3. SAP MIGO收货界面'批次'分类选项卡里不出现'分类'按钮之对策
  4. 2019最强就业指南,看了达摩院十大科技趋势,再也不怕互联网寒冬
  5. 到2020年,智能手机将拥有十项AI功能,有些可能会出乎你意料
  6. gitzip没有作用以及github如何下载单个文件或目录
  7. 深入理解Pytorch之register_buffer
  8. module ‘torchtext.data‘ has no attribute ‘LabelField‘
  9. 清华博士后用10分钟讲解AlphaCode背后的技术原理,原来程序员不是那么容易被取代的!...
  10. IEEE Spectrum调查:AI 的 6 种最坏情况