`

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/

分享到:
评论

相关推荐

    iOS开发多线程-GCD介绍 - iOS知识库1

    iOS开发多线程-GCD介绍 一、简单介绍 GCD(Grand Central Dispatch)是苹果公司推出的多核并行运算解决方案,自动利用更多的CPU内核,自动管理线程的生命周期,程序员只需要告诉GCD想要执行什么任务,不需要编写...

    swift-GCD使用大全

    本资源“swift-GCD使用大全”旨在全面介绍GCD的常用和不常用API,通过示例代码帮助你深入理解其应用场景和用法。 1. **GCD基础概念** GCD是一种基于C语言的底层任务调度系统,但在Swift中被广泛使用。它是基于队列...

    GCD多线程_demo

    本教程通过"GCDDemo"项目,将详细介绍如何利用GCD进行iOS多线程编程,并展示其与Block的结合使用,以提升代码的简洁性和可读性。 1. GCD基础 GCD是一种基于C语言的底层API,它由Apple引入,用于简化并发编程。GCD...

    iOS GCD 多线程

    本文档将详细介绍如何利用GCD实现不同优先级的子队列,并通过实例演示其工作原理。 #### 二、创建子队列与设置优先级 在GCD中,我们可以通过创建自定义队列并将其作为全局队列的子队列来间接地为其设置优先级。...

    Pro Multithreading and Memory Management for iOS

    - **Blocks入门**:第四章提供了Blocks的基础介绍,包括如何定义和使用Blocks,以及它们如何与内存管理相互作用。 - **Blocks实现**:第五章进一步探讨了Blocks的底层实现机制,这对于理解Blocks如何与其他技术(如...

    一些经典算法介绍--算法大全(txt版)

    以上介绍了最大公约数、最小公倍数以及素数检测的经典算法。这些算法不仅在数学领域有着广泛的应用,在计算机科学中也非常重要,尤其是在数据结构与算法设计、密码学等领域中发挥着关键作用。通过对这些基础算法的...

    iOS开发你需要知道的

    2. GCD队列创建:讲解如何使用dispatch_queue_create创建GCD队列。 3. RunLoop:深入理解RunLoop的工作原理及其在iOS中的应用。 十四、其他 1. Cordova跨平台方案:介绍如何使用Cordova构建跨平台iOS应用。 2. ...

    有理数四则运算设计性试验报告

    - 设计思路:介绍所采用的数据结构和算法设计。 - 实现细节:列出关键代码段。 - 测试案例:展示输入数据、预期结果及实际运行结果。 - 问题与反思:总结实验中遇到的问题、解决方案以及个人感悟。 通过这个...

    iOS中多线程原理与runloop介绍

    ### iOS中多线程原理与runloop介绍 #### 一、线程概述 在iOS开发中,线程是构成程序的基本单位之一。一个程序至少包含一个线程——主线程(Main Thread),它负责应用程序的主要逻辑及用户界面的绘制。主线程在iOS...

    吉林大学ACM代码库全集(.pdf)

    - **GCD最大公约数**:介绍了求解两个整数最大公约数的方法。 - **快速GCD**:探讨了快速求解最大公约数的算法。 - **扩展GCD**:讲解了如何通过扩展欧几里得算法求解最大公约数。 - **模线性方程A*X=B(%N)**:介绍...

    求最大公约数和最小公倍数的方法C++

    本文将详细介绍如何用C++语言来实现这两种运算。 一、最大公约数(GCD) 最大公约数是指两个或多个非零整数的最大正整数,这些整数都能整除这个数。在C++中,我们可以使用欧几里得算法(Euclidean Algorithm)来计算...

    基础间隔架[手册].pdf

    综上所述,《基础间隔架[手册].pdf》是一份详细介绍了基础间隔架产品特性和使用方法的手册。它不仅包含了重要的安全警示信息,还提供了多种语言版本的安装与使用指南,以确保用户能够安全、正确地使用该产品。对于...

    Java编写的大整数四则运算

    Java语言通过内置的`BigInteger`类提供了解决方案,但本文档介绍的是一个自定义实现的Java程序,用于执行大整数的加、减、乘、除以及求最大公约数(GCD)和最小公倍数(LCM)的操作,而不会出现溢出问题。...

    DelayTest.zip

    下面将详细介绍这四种方法及其应用场景。 1. **定时器(Timer)** 定时器是Objective-C中最常见的实现延时操作的方式之一,它基于RunLoop工作。创建一个NSTimer实例,设置好时间间隔,将其添加到当前RunLoop中即可...

    《iPhone4与iPad开发基础教程》PDF版本下载.txt

    - **GCD**:深入理解Grand Central Dispatch机制,实现多线程任务调度。 - **Operation Queues**:学习如何使用Operation Queues进行复杂任务管理。 - **异步编程模式**:介绍常见的异步编程模式,如Completion ...

    [iPhone和iPad开发书籍大全].Cocoa.Recipes.for.Mac.OS.X.2nd(Peachpit.Press.2010-03)

    #### 四、书籍价值与适用人群 **本书适用于**: - Mac OS X应用程序开发者 - 对Cocoa框架感兴趣的学习者 - 希望深入了解Mac应用程序开发的技术人员 **价值点**: - 提供了大量的实战案例,帮助读者快速掌握Cocoa框架...

    matlab函数集 常用函数介绍

    以下是对MATLAB常用函数的详细介绍: 1. **基本数学函数**: - `abs(x)`:计算实数或复数的绝对值,对于向量,返回每个元素的绝对值。 - `angle(z)`:返回复数 `z` 的相角,即弧度制的角度。 - `sqrt(x)`:求...

    ProgramminginObjective-C4thEdition

    这本书的第四版更新了最新的编程实践,包括Swift与Objective-C的交互,以及Apple最新的开发工具Xcode的相关内容。 1. **Objective-C基础**:Objective-C是在C语言基础上扩展的面向对象的语言,它的核心特性包括消息...

Global site tag (gtag.js) - Google Analytics