GCD简介

GCD(Grand Central Dispatch)是苹果公司libdispatch库的商业名称,它是一个在多核iOS或OS X平台上提供代码并行运行的库。它有以下好处:

  1. 简单易用:GCD提供了一个相对于线程和锁更加简单的并行编程模型,你可以只用专注于任务,而不用关心线程的创建和管理。
  2. 高效:GCD会根据系统负载自动调整线程的数量,优化任务的调度,这就减少了线程创建和上下文切换的开销,提高了性能。

一些多线程编程的术语

串行和并行(Serial vs. Concurrent)

串行是指在一个时间只能有一个任务处于运行状态,一个任务只能在当前任务运行结束后才可以开始运行。 并行指一个时间可以有多个任务同时处于运行状态。

同步和异步(Synchronous vs. Asynchronous)

同步是指一个function只能在它执行的任务完成后才会返回。 异步指一个function会立即返回而不用等待它的任务执行完成。

临界区(Critical Section)

临界区是指一段不能并行执行的代码段。

条件竞争(Race Condition)

条件竞争是指多进程或多线程并发访问或操作同一个数据时执行结果和访问顺序有关的现象。

死锁(Deadlock)

当一个线程在等待另一个线程执行完成以继续执行,而另一个线程又在等待这个线程执行完成时就会发生死锁。

线程安全(Thread Safe)

当一段代码可以从多个线程并行执行而不会产生任何负面效果时,这段代码就是线程安全的。

上下文切换(Context Switch)

上下文切换是指进程从一个线程切换到另一个线程执行时,需要保存当前线程的执行状态,并恢复另一个线程的执行状态。

Dispatch Queues

dispatch queues是GCD提供的一种简单的用来管理任务的队列,被添加到dispatch queues队列中的任务会以FIFO的顺序来执行,即先被添加到队列中的任务总是会先开始执行。dispatch queues是线程安全的,你可以同时从多个线程并发地访问它们而不会有任何问题。dispatch queues分两种:

串行队列(Serial Queues)

串行队列执行任务示意图

串行队列同一时间只会执行一个任务,每一个任务只会在前面一个任务执行结束后才会开始执行。一个任务开始执行的时间和它前面任务的结束时间是不确定的。串行队列中所有任务的执行顺序也是按照它们加入队列的顺序来确定的。因为同一时间只有一个任务处于运行状态,所以不用担心它们会并发地访问同一个临界区。

并行队列(Concurrent Queues)

并行队列执行任务示意图

并行队列中的任务也是按照它们加入队列的顺序依次开始执行的,但这些任务可能以任意顺序结束运行。当两个任务的运行时间发生重叠时,GCD可能把一个任务放到另一个核上运行,也可能发生线程切换。

有哪些dispatch queue可以使用

main queue

系统提供一个名为main queue的串行队列,main queue中的任务都会在主线程上执行,主线程是唯一可以更新UI的线程。

global queue

系统同时提供了名为global dispatch queue的并行队列,global dispatch queue有四种优化级:background, low, default, high。

custom queue

你也可以使用dispatch_queue_create来创建自己的串行或并行队列。

GCD常用方法

dispatch_sync

同步执行一个任务,会等待任务完成再继续执行当前任务。系统会尽可能在当前线程上执行该任务。

dispatch_async

异步执行一个任务,不会等待任务完成,继续执行当前任务。

dispatch_after

延迟一段时间后开始执行任务。

dispatch_once

dispatch_once以线程安全的方式执行且仅执行代码块一次。当一个线程在执行dispatch_once代码块时,另一个试图执行该代码块的线程会被block,直到dispatch_once代码块执行完成。dispach_once常用于创建单例对象。

dispatch_barrier_async

异步地把一个任务添加到队列中,该任务会在所有之前加入队列的任务都执行完毕后才开始执行。所有在此任务之后加入的任务,也会在该任务执行完成之后才开始执行。dispatch_barrier_sync与此类似。

参考文档

  1. Grand Central Dispatch In-Depth: Part 1/2
  2. Concurrency Programming Guide
Written on January 30, 2018
View: