一、Dispatch Queue挂起
dispatch queue可以被挂起和恢复。使用 dispatch_suspend函数来挂起,使用  dispatch_resume 函数来恢复。这两个函数的行为是如你所愿的。另外,这两个还是也可以用于dispatch source。
一个要注意的地方是,dispatch queue的挂起是block粒度的。换句话说,挂起一个queue并不会将当前正在执行的block挂起。它会允许当前执行的block执行完毕,然后后续的block不再会被执行,直至queue被恢复。
还有一个注意点:从man页上得来的:如果你挂起了一个queue或者source,那么销毁它之前,必须先对其进行恢复。
二、Dispatch Queue目标指定
所有的用户队列都有一个目标队列概念。从本质上讲,一个用户队列实际上是不执行任何任务的,但是它会将任务传递给它的目标队列来执行。通常,目标队列是默认优先级的全局队列。
用户队列的目标队列可以用函数 dispatch_set_target_queue来修改。我们可以将任意dispatch queue传递给这个函数,甚至可以是另一个用户队列,只要别构成循环就行。这个函数可以用来设定用户队列的优先级。比如我们可以将用户队列的目标队列设定为低优先级的全局队列,那么我们的用户队列中的任务都会以低优先级执行。高优先级也是一样道理。
有一个用途,是将用户队列的目标定为main queue。这会导致所有提交到该用户队列的block在主线程中执行。这样做来替代直接在主线程中执行代码的好处在于,我们的用户队列可以单独地被挂起和恢复,还可以被重定目标至一个全局队列,然后所有的block会变成在全局队列上执行(只要你确保你的代码离开主线程不会有问题)。
还有一个用途,是将一个用户队列的目标队列指定为另一个用户队列。这样做可以强制多个队列相互协调地串行执行,这样足以构建一组队列,通过挂起和暂停那个目标队列,我们可以挂起和暂停整个组。想象这样一个程序:它扫描一组目录并且加载目录中的内容。为了避免磁盘竞争,我们要确定在同一个物理磁盘上同时只有一个文件加载任务在执行。而希望可以同时从不同的物理磁盘上读取多个文件。要实现这个,我们要做的就是创建一个dispatch queue结构,该结构为磁盘结构的镜像。
首先,我们会扫描系统并找到各个磁盘,为每个磁盘创建一个用户队列。然后扫描文件系统,并为每个文件系统创建一个用户队列,将这些用户队列的目标队列指向合适的磁盘用户队列。最后,每个目录扫描器有自己的队列,其目标队列指向目录所在的文件系统的队列。目录扫描器枚举自己的目录并为每个文件向自己的队列提交一个block。由于整个系统的建立方式,就使得每个物理磁盘被串行访问,而多个物理磁盘被并行访问。除了队列初始化过程,我们根本不需要手动干预什么东西。
三、信号量
dispatch的信号量是像其他的信号量一样的,如果你熟悉其他多线程系统中的信号量,那么这一节的东西再好理解不过了。
信号量是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。
我们使用函数  dispatch_semaphore_create 来创建dispatch信号量,使用函数  dispatch_semaphore_signal 来信号通知,使用函数 dispatch_semaphore_wait 来等待。这些函数的man页有两个很好的例子,展示了怎样使用信号量来同步任务和有限资源访问控制。
单次初始化
GCD还提供单词初始化支持,这个与pthread中的函数  pthread_once 很相似。GCD提供的方式的优点在于它使用block而非函数指针,这就允许更自然的代码方式:
这个特性的主要用途是惰性单例初始化或者其他的线程安全数据共享。典型的单例初始化技术看起来像这样(线程安全的):
    + (id)sharedWhatever
    {
        static Whatever *whatever = nil;
        @synchronized([Whatever class])
        {
            if(!whatever)
                whatever = [[Whatever alloc] init];
        }
        return whatever;
    }
这挺好的,但是代价比较昂贵;每次调用  +sharedWhatever 函数都会付出取锁的代价,即使这个锁只需要进行一次。确实有更风骚的方式来实现这个,使用类似双向锁或者是原子操作的东西,但是这样挺难弄而且容易出错。
使用GCD,我们可以这样重写上面的方法,使用函数 dispatch_once:
    + (id)sharedWhatever
    {
        static dispatch_once_t pred;
        static Whatever *whatever = nil;
        dispatch_once(&pred, ^{
            whatever = [[Whatever alloc] init];
        });
        return whatever;
    }
这个稍微比 @synchronized方法简单些,并且GCD确保以更快的方式完成这些检测,它保证block中的代码在任何线程通过  dispatch_once 调用之前被执行,但它不会强制每次调用这个函数都让代码进行同步控制。实际上,如果你去看这个函数所在的头文件,你会发现目前它的实现其实是一个宏,进行了内联的初始化测试,这意味着通常情况下,你不用付出函数调用的负载代价,并且会有更少的同步控制负载。

转载自:http://www.dreamingwish.com/dream-2012/gcd-four-the-the-odds-and-ends.html

GCD简介四:挂起,目标指定,信号量相关推荐

  1. GCD简介一:基本概念和Dispatch Queue

    一.什么是GCD? Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写.从基本功能上讲,GCD有点像NSOperationQueue,他们都 ...

  2. 《软件工程》第四次作业--目标软件(必应词典)

    <软件工程>第四次作业--目标软件(必应词典)    首先说明:选择的目标软件是 必应词典(Androi 4.2.6版)      1.列举目标软件的目标用户?(10分) 从职业来看,用户 ...

  3. AI:人工智能领域算法思维导图集合之有监督学习/无监督学习/强化学习类型的具体算法简介(预测函数/优化目标/求解算法)、分类/回归/聚类/降维算法模型选择思路、11类机器学习算法详细分类之详细攻略

    AI:人工智能领域算法思维导图集合之有监督学习/无监督学习/强化学习类型的具体算法简介(预测函数/优化目标/求解算法).分类/回归/聚类/降维算法模型选择思路.11类机器学习算法详细分类(决策树/贝叶 ...

  4. 输入一个字符,一个数字,一个单精度浮点数,一个双精度浮点数,按顺序输出它们四个 且数字指定占4个字符宽靠右对齐,单精度浮点数保留2位小数,双精度保留12位小数,占一行输出、空格分隔

    1810: 输入一个字符,一个数字,一个单精度浮点数,一个双精度浮点数,按顺序输出它们四个 且数字指定占4个字符宽靠右对齐,单精度浮点数保留2位小数,双精度保留12位小数,占一行输出.空格分隔 #in ...

  5. 哈工程计算机学院研究生导师,哈尔滨工程大学自动化研究生导师简介四.doc

    哈尔滨工程大学自动化研究生导师简介 四 ? 莫宏伟男,1973年5月生,工学博士,教授,博士生导师 模式识别与智能系统研究所副所长 指导博士生学科:模式识别与智能系统 指导硕士生学科:第一专业:模式识 ...

  6. GCD简介三:Dispatch Sources

    一.何为Dispatch Sources 简单来说,dispatch source是一个监视某些类型事件的对象.当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中 ...

  7. Keil(MDK-ARM-STM32)系列教程(四)工程目标选项配置(Ⅱ)

    Ⅰ.写在前面 本文接着上一篇文章"工程目标选项配置(Ⅰ)"进行讲述工程目标选项中后五项的配置,也就是C/C++.Asm.Linker.Debug.Utilities这五项配置的具体 ...

  8. GCD简介二:多核心的性能

    一.概念 为了在单一进程中充分发挥多核的优势,我们有必要使用多线程技术.在低层,GCD全局dispatch queue仅仅是工作线程池的抽象.这些队列中的Block一旦可用,就会被dispatch到工 ...

  9. 一、STM32简介、选型及其目标

    STM32简介 STM32系列是由意法半导体公司推出的ARM Cortex-M内核单片机,从字面上来看,ST为意法半导体公司的缩写,M是Microcontrollers即单片机的缩写,32代表32位 ...

最新文章

  1. P4619 [SDOI2018]旧试题(莫比乌斯反演,建图优化三重枚举,三元环计数,神仙好题,超级清晰易懂)
  2. jsp:include和%@include%的区别
  3. 魅族 C++ 微服务框架技术内幕揭秘
  4. java中无法推断类型参数_Java 10中的本地类型推断,或者如果它像鸭子一样嘎嘎叫...
  5. Web服务器处理Servlet处理请求过程
  6. Java之父:Solaris前景堪忧
  7. Atitit 类库冲突解决方案  httpclient-4.5.2.jar
  8. QTsocket网络编程
  9. Linux忘记密码修改密码
  10. 流程图中的实线_教你如何正确看懂工艺流程图
  11. 易语言php验证码识别,易语言自动打码验证码服务端带案例
  12. PR更改视频画布大小。PR剪裁视频。PR导出视频时的适应视屏大小都是啥意思啊?
  13. 微信公众号运营必备神器汇总
  14. 电源 PFC(功率因数校正)电路拓扑,共计100多份,内含A PFC,连续断续,交错,维也纳,各功率段的PFC电路,还有电感 设计选型
  15. 利用echart和echart-gl绘制江苏省的地图之二
  16. 不如意的人生,才是真实的。
  17. ico的尺寸_Favicon.ico浏览器图标文件制作和正确使用
  18. 回首过去 展望未来
  19. TTL(生存时间)介绍
  20. PNG warning: iCCP: known incorrect sRGB profile

热门文章

  1. 使网页成黑白色调的滤镜(转)
  2. python学习之数据类型(int,bool,str)
  3. 洛谷 P1377 [TJOI2011]树的序 解题报告
  4. Gradle 下载不了
  5. centos 账号安全设置
  6. 实验五 — — Java网络编程及安全
  7. MACIOS Socket编程
  8. Oracle修改表空间大小
  9. 数据结构——二叉搜索树的C语言实现
  10. python-k近邻分类器-KNN