`

GCD介绍(四): 完结

阅读更多

原文地址:http://www.tanhao.me/pieces/362.html/

 

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 调用之前被执行,但它不会强制每次调用这个函数都让代码进行同步控制。实际上,如果你去看这个函数所在的头文件,你会发现目前它的实现其实是一个宏,进行了内联的初始化测试,这意味着通常情况下,你不用付出函数调用的负载代价,并且会有更少的同步控制负载。

结论

这一章,我们介绍了dispatch queue的挂起、恢复和目标重定,以及这些功能的一些用途。另外,我们还介绍了如何使用dispatch 信号量和单次初始化功能。到此,我已经完成了GCD如何运作以及如何使用的介绍。

该系列文章转载自:http://www.dreamingwish.com/

分享到:
评论

相关推荐

    GCD实战二:资源竞争 - 51CTO.COM1

    GCD实战二:资源竞争 - 51CTO.COM1

    GCD实战一:使用串行队列实现简单的预加载 - 51CTO.COM1

    GCD实战一:使用串行队列实现简单的预加载 - 51CTO.COM1

    Coursera_GCD_Project:获取和清理数据项目

    标题 作者 日期 输出 GettingAndCleaningData_Project_ReadMe 道格·奥尔森(Doug Olson) 2015年6月20日 ... 接下来是我的run_analysis.R脚本的演练,并添加了dim()和str()的一些额外实例(希望如此)有助于澄清...

    GCD_CP:Coursera 获取和清理数据 - 课程项目

    获取和清理数据 - 编程作业 自述文件 获取和清理数据:课程项目 这个自述文件解释了如何使用和运行 run_analysis.R 脚本 ##目的和数据来源 该脚本是为 Coursera“获取和清理数据”课程项目编写的,该项目使用从三星 ...

    Poly_GCD_POWER_6_July2005.zip_gcd_gcd for polynomial_gcd matlab_

    If we need to verify the fact that a Polynomial has...a) A function to compute the GCD of 2 Polynomials. Since I could not find a Standard Matlab function for this, I created this function : Poly_GCD.m :

    gcd-project:获取和清理数据课程项目

    gcd-项目获取和清理数据课程项目gcd-project 存储库包括以下文件: 'README.md' '密码本.md' 'run_analysis.R' '整理数据.txt' 笔记 : Run_analysis 脚本位于“UCI HAR 数据集”目录中,该目录还包含训练和测试...

    DS-GCD-CourseProject:课程项目

    DS-GCD课程计划该项目的目的是演示如何从给定的数据集中准备整齐的数据集。 对于此项目,使用了现有数据集,该数据集是从Samsung Galaxy S智能手机的加速度计中收集的。 有关此数据的完整描述,请参见。 用于项目的...

    GCD_CourseProject:课程项目,获取和清理数据

    GCD_课程项目获取和清理数据课程项目###Repo 此 Repo 包含以下文件和目录: 输入原始数据: UCI HAR 数据集,来源: ://d396qusza40orc.cloudfront.net/getdata/projectfiles/UCI HAR Dataset.zip 。 完整说明可在...

    GCD_Project:用于获取和清理数据项目

    标题 作者 日期 输出 自述文件 赛阿斯兰 2015 年 1 月 25 日,星期日 ... 这是“获取和清理数据课程项目工作”的提交。 该提交仅包含一个名为 run_analysis.R 的脚本。... 脚本中名为 run_analysis 的这个函数只接受一个...

    GCD_CourseProject:获取和清理数据课程项目

    GCD_课程项目 获取和清理数据课程项目文件包括: 包含在 repo 中的 README.md 文件 CodeBook.md 描述变量、数据以及为清理数据而执行的任何转换或工作的代码簿 run_analysis.R 脚本 ================== 运行脚本 a)...

    gcd_proj:Coursera 课程“获取和清理数据”

    gcd_proj Coursera 课程“Getting and Cleaning Data”:课程项目介绍目前所有数据科学中最令人兴奋的领域之一是可穿戴计算。 Fitbit、Nike 和 Jawbone Up 等公司正在竞相开发最先进的算法来吸引新用户。 从课程网站...

    GCD_CourseProjectPasBesoin:获取和清理数据课程的课程项目

    GCD_CourseProjectPasBesoin 获取和清理数据课程的课程项目 准备 从下载数据集并解压; 把它放在 repo 的顶部。 它应该被称为“UCI HAR 数据集”。 这个目录会被 Git 忽略,不会被添加到 repo 中。 跑步 只有一种...

    gcd-django:大漫画数据库网站

    GCD Web应用程序 该文件的最新更新: 2020年8月 这是Grand Comics数据库的当前实现,托管在 (生产)和 (新功能的公共Beta版)上。 请参阅和的“以获取有关我们的工作方式和迄今为止所做的工作的更多详细信息。 该...

    GCD_Project:获取和清理数据课程项目

    这个 repo 包含我为 GCD 课程项目提交的四个文件。 此 README 文件提供了项目的概述。 将提供的原始数据转换为最终数据的 R 脚本。 记录最终数据集的数据码本。 以及最终整洁的数据集本身。 背景 收集原始数据以...

    GCD异步获取图片

    GCD异步获取图片

    GCD_CourseProject:课程项目作业文件

    GCD_课程项目##课程项目分配文件###run_analysis.R 的自述文件这个 README.md 的目的是逐步解释 run_analysis.R 文件是如何工作的*在开始时,代码正在读取相关的原始数据 - 数据路径以相对路径的形式提供,因此为了...

    GCD_Project:获取和清理数据课程项目回购

    GCD_项目 获取和清理数据课程项目回购 这个脚本是如何工作的…… 首先,从您的工作目录中,您需要下载并提取以下数据集: : 有了工作目录中的数据,您就可以按如下方式使用 run_analysis.R。 在相应的工作目录中...

    GCD_CourseProject:获取和清理数据

    获取和清理数据:课程项目:自述文件 由 Manoj Chandrasekar 提交 步骤1: 下载原始数据。 如果数据文件不存在,取消注释“url <...”和“download.fi...”行以下载数据文件 # url <... zipFile <...

    gukaifeng#hexo#Maximum-GCD(最大公约数)1

    title: Maximum GCD(最大公约数)categories: [算法题解]传送门:UVA 11827 - Maximum GCD题目大意:给你几组数

Global site tag (gtag.js) - Google Analytics