type
status
date
slug
summary
tags
category
icon
password
在上一篇文章中,了解进程及线程的基础知识,我们在本文探讨在iOS开发中所遇到的多线程方案,以及方案中涉及的相关概念。
一、多线程的方案
以上方案,除去
pthread
跨平台的方案,其他基于Objective-C
苹果独有的方案,我们将在后面系列的文章中逐一阐述。二、队列与同步异步
2.1 队列
在说明队列之前,先对几个概念再次重温:
- 进程(process)用于指代一个正在运行的可执行程序,它可以包含多个线程。
- 线程用于指代独立执行的代码段,在 iOS 中,线程的底层实现是基于 POSIX threads API 的,也就是我们常说的
pthreads
。
- 任务(task)用于指代抽象的概念,表示需要执行工作,可以理解为就是一段代码。
队列是一种先进先出(FIFO)线性的数据结构,是计算机系统为了对任务进行调度的一种抽象化机制——在线程 与任务之间搭建起桥梁,即将任务调度分配到具体的线程上。
一个队列由一个或多个任务组成,当这些任务要开始执行时,系统会分别把他们分配到某个线程上去执行。
至于队列是串行还是并发,区别在于队列执行任务的方式——是否等待当前任务结束。
ㅤ | 串行队列 | 并发队列 |
是否等待当前任务结束 | 是 | 否 |
表现 | 只能一个接着一个执行任务 | 可以并发执行任务 |
线程 | 每次对应一个线程,这个线程可能不变,也可能被更换 | 可能对应多个线程,也可能对应一个线程 |
注意上面两个关键词:只能、可以。
只能表示串行队列,一定是任务一个一个接着执行,不可能并发。
可以表示任务可以并发执行,但并不一定是并发执行的。因为,还需要看任务是否是同步还是异步提交的。
串行队列
并发队列
2.2 同步与异步
同步和异步操作的主要区别在于是否等待当前任务完成,亦即是否阻塞当前线程。
ㅤ | 同步操作 | 异步操作 |
是否等待当前操作结束 | 是 | 否 |
是否阻塞线程 | 是
执行完成才继续执行后续代码 | 否
调用后立即返回执行后续代码 |
应用场景 | 简单任务,顺序依赖 | 长时间运行任务,提高响应性 |
针对上面的术语,在iOS中:
三、各种队列的同步异步
下面我们针对各种队列的同步异步,进行代码演练,并进行总结,如下:
需要注意的是:在执行同步任务的过程中,系统会进行优化,一般来说,会将同步操作加入到当前正在运行的线程中去。
3.1 GCD
其中以GCD的方式来进行。
3.2 主队列
iOS 主队列本质是一个串行队列。
3.2.1 主队列同步
主队列-同步:崩溃
- 依次将任务提交到主队列:syncOperationMainThread、任务1;
- 在主线程先执行syncOperationMainThread,其内部需要执行任务1;
- 但执行任务1,根据串行队列的特点,又需要执行完syncOperationMainThread;
- 相互依赖对方执行完才能继续执行,产生死锁,崩溃。
3.2.2 主队列异步
主队列-异步
- 依次提交任务到主队列,所以是asyncOperationsOnMainThread,任务1;
- 主队列在主线程执行,执行asyncOperationMainThread,其中遇到任务1;
- 由于任务1是异步提交的,所以不需要等待任务1返回,可以继续asyncOperationMainThread;
- 执行完asyncOperationMainThread,继续在主线程执行异步提交的任务1。
3.3 串行队列
3.3.1 串行队列同步
串行队列-同步
- 主线程执行syncOperationsOnSerialThread;
- 将任务1同步提交到一个串行队列"serial",队列"serial",由于同步 任务不会创建新线程,所以在主线程执行任务1,由于是同步,需要等待执行完;
- 任务1执行完,回到主线程继续执行syncOperationsOnSerialThread。
3.3.2 串行队列异步
串行队列-异步
- 主线程执行asyncOperationsOnSerialThread;
- 将任务1异步提交到串行队列,队列将分配新线程执行任务1,由于是异步提交,无须立即返回结果和等待。回到主线程继续执行asyncOperationsOnSerialThread;
- 执行完asyncOperationsOnSerialThread,新线程依次执行任务1;
3.4 全局队列
全局队列本质上是一个并发队列。
3.4.1 全局队列同步
全局队列-同步
1.在主线程执行syncOperationsOnGloabThread;
2.将任务1提交到全局队列,遇到任务1,由于是同步提交,需要立即执行任务1,阻塞当前主线程;
2.1 原本任务1提交全局队列,是个并发队列,也就是任务1原本可以在多个线程并发执行,但由于同步需要单个任务串行执行;
2.2 而且由于同步操作的优化,原本任务1会在主线程之外的新进程串行进行,此处也会优化成在主线程执行;
3.待任务1执行完之后,继续执行syncOperationsOnGloabThread;
3.4.2 全局队列异步
全局队列-异步
- 在主线程执行asyncOperationsOnGloabThread;
- 将任务1提交到全局队列,并且以异步方式提交,立即会在其他线程执行任务1;
- 继续执行asyncOperationsOnGloabThread;
- 继续执行任务1,并且全局队列会调度多个新线程并发执行任务1。
3.5 并发队列
3.5.1 并发队列同步
并发队列-同步
- 执行syncOperationsOnConcurrentThread;
- 同步提交任务1到并发队列,由于是同步,将会等待任务1执行完毕;
- 并且由于优化,将同步任务分配到主线程执行;
- 执行完任务1后,继续执行syncOperationsOnConcurrentThread。
3.5.2 并发队列异步
并发队列-异步
- 执行asyncOperationsOnConcurrentThread
- 异步提交任务1到并发队列,由于异步提交,将会继续执行asyncOperationsOnConcurrentThread;
- 执行完后,并发队列将任务1分配到多个线程执行任务1
参考
链接
- 《深入解析Mac OS X & iOS 操作系统》
示例代码