iOS开发:深入理解GCD(一)

本文参考《iOS与OS X多线程和内存管理》以及其他博客。
进程: 进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例�。程序运行时系统会创建一个进程,并为它分配资源,然后将该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。简单说,就是一个正在运行的应用程序。
线程: 线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量,线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。
  一个进程至少有一个线程,即主线程。在iOS开发中,所有涉及UI界面的,必须在主线程中更新。
什么是GCD?
  苹果官方给出解释:GCD是异步执行任务的技术之一,一般将应用程序中记述的线程管理代码在系统几种实现,开发者只需要定义想执行的任务更追加到适当的Dispatch Queue中,GCD就可以生成必要的线程并计划执行任务。
它有如下优点:
  1. GCD可以将花费时间极长的任务放到后台线程,可以改善应用的相应性能。
  2. GCD提供一个易于使用的并发模型而不仅仅只是锁和线程,以帮助我们避开并发陷阱。
  3. GCD具有常见模式(如单例)上用更高性能的优化代码的潜在能力
GCD的一些术语
串行(Serial)与并发(Concurrent)
  任务串行,在同一时间,有且只有一个任务被执行,即一个任务执行完毕之后再执行下一个任务。
  任务并发,在同一时间,有多个任务被执行。
同步(Synchronous)与异步(Asynchronous)
  同步,意味着在当前线程中执行任务,不具备开启新的线程的能力。
  异步,在新的线程中执行任务,具备开启新的线程的能力。
  在GCD中,这些术语描述当一个函数相对于另一个任务完成,此任务是该函数要求GCD执行的,一个同步函数只在完成了它预订的任务后才返回。一个异步函数,刚好相反,会立即返回,预订的任务会完成但不会等它完成,因此,一个异步函数不会阻塞当前线程去执行下一个函数。
临界区(Critical Section)
  就是一段代码不能被并发执行,即两个线程不能同时执行这段代码。这很常见,因为代码去操作一个共享资源,如数据库写入操作。
死锁(Deadlock)
  停止等待事情的线程会导致多个线程互相维持等待,即死锁。
  两个或多个线程都卡主了,并等待对方完成或执行其他操作。如在串行队列中使用该串行队列同步的执行任务。
线程安全(Thread Safe)
  线程安全的代码能在多线程或并发任务中被安全的调用,而不会导致问题(数据损坏,崩溃等)。线程不安全的代码在某个时刻只能在一个上下文中运行。线程安全的代码如NSDictionary,可以在同一时间在多个线程中使用它而不会有问题。另线程不安全代码如NSMutableDictionary,应该保证一次只能有一个线程访问它。
上下文切换(Context Switch)
  一个上下文切换指当你在单个进程里切换执行不同的线程时存储与恢复执行状态的过程。
并发和并行
  并行要求并发,但并发不能保证并行。开启线程是很耗性能的,事实上,在某次并行处理任务中,开启的线程数量是有限的,如果上限为2,每次开启的新线程是2,那么有可能出现并发却并不并行的情况。
  并发代码的不同部分可以“同步”执行,但具体情况都依赖系统,多核设备通过并行来同时执行多个线程,而单核设备要实现这一点,必须先运行一个线程,执行一个上下文切换,然后运行另一个线程或进程。这通常发生的足够快以至我们会有并发执行的错觉。
队列(Queue)
  苹果官方说明:开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。

dispatch_async(queue,^{
/**
* 想要执行的任务
*/
});

  该源码使用Block“定义想执行的任务”,通过dispatch_async函数“追加”赋值在变量queue的Dispatch Queue中。这样,可以使得指定的Block在另一线程中执行。
  GCD提供Dispatch queue 来出来代码块,这些对联管理开发者提供给GCD的任务并用FIFO(先进先出)顺序执行这些任务。这就保证了第一个被添加到队列里的任务会是队列中第一个开始的任务,而第二个被添加的任务将第二个开始,如此直到队列的终点。

  Dispatch Queue是执行处理的等待队列,开发者通过dispatch_async等API,在block语法中记述想要执行的处理,并将其追加到Dispatch Queue中。Dispatch Queue按照追加的顺序进行处理。
  所有的Dispatch Queue自身都是线程安全的,能从多个线程并行的访问它们。其中DispatchQueue中有两种,一种是等待现在执行中处理的Serial Dispatch Queue,另一种是Concurrent Dispatch Queue。
串行队列(Serial Dispatch Queue)

  这些任务执行时受到GCD的控制,唯一能确保的事情是GCD一次只执行一个任务,并且按照我们添加到队列的顺序来执行。

dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.test", DISPATCH_QUEUE_SERIAL);
    dispatch_async(dispatchQueue, ^{
        NSLog(@"任务一开始");
        sleep(5);
        NSLog(@"任务一完成");
    });
    dispatch_async(dispatchQueue, ^{
        NSLog(@"任务二开始");
        sleep(4);
        NSLog(@"任务二完成");
    });
    dispatch_async(dispatchQueue, ^{
        NSLog(@"任务三开始");
        sleep(3);
        NSLog(@"任务三完成");
    });

打印结果如下

并发队列(Concurrent Dispatch Queue)  并发队列中的任务能得到的保证是它们会按照被添加的顺序开始执行。任务是以任意顺序完成,你不会知道何时开始下一个任务,或者任意时刻有多少Block执行,这完全取决于GCD

    dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.test", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 100; i++) {
        dispatch_async(dispatchQueue, ^{
            NSLog(@"%d   %@",i, [NSThread currentThread]);
        });
    }

打印结果

可以看到,不是顺序执行任务,开了多个线程。使用多个线程同时处理多个任务,因为完成任务所需要消耗的时间不同,完成任务的最终时间不同。

Serial Dispatch Queue与Concurrent Dispatch Queue和线程之间的关系如图:
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335