iOS高级开发工程师面试——多线程
iOS高级开发工程师面试——多线程
- 一、什么是进程?什么是线程?进程和线程的关系?什么是多进程?什么是多线程?
- 二、iOS开发中有多少类型的线程?分别对比?
- 三、GCD有哪些队列,默认提供哪些队列?
- 四、GCD有哪些方法 api?
- 五、GCD主线程 & 主队列的关系?
- 六、如何实现同步?有多少方式就说多少
- 七、dispatch_once 实现原理 ?
- 八、什么情况下会死锁?死锁的应对策略有哪些?怎么避免死锁?
- 九、有哪些类型的线程锁?分别介绍下作用和使用场景?
- 十、iOS各种锁的性能,琐是毫秒级别还是微妙级别?
- 十一、NSOperationQueue 中的 maxConcurrentOperationCount 默认值
- 十二、NSTimer、CADisplayLink、dispatch_source_t 的优劣?
- 十三、多线程可以访问同一个对象吗 ?多进程呢?
一、什么是进程?什么是线程?进程和线程的关系?什么是多进程?什么是多线程?
1. 进程:
-
进程是一个具有独立功能的程序关于某次数据集合的一次运行活动,他是操作系统分配资源的基本单位。
-
进程是指系统正在运行中的一个应用程序,就是一段程序执行的过程。我们可以理解为手机上的一个app。
-
每个进程之间是独立的。每个进程均运行在起专用且受保护的内存空间内,拥有独立运行所需的全部资源。
-
进程是操作系统进行资源分配的单位。
2. 线程:
-
程序执行流的最小单元,线程是进程中的一个实体。
-
一个进程想要执行任务,必须至少有一条线程。应用程序启动的时候,系统会默认开启一条线程,也就是主线程。
3. 进程和线程的关系:
-
线程是进程的执行单元,进程的所有任务都在线程中执行。
-
线程是CPU分配资源和调度的最小单位。
-
一个程序可对应多个进程(多进程);一个进程中可对应多个线程,但至少要有一条线程。
-
同个进程内的线程共享进程资源。
4. 多进程:
-
进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然程序是死的(静态的),进程是活动的(动态的)。
-
进程可以分为系统进程和用户进程。
系统进程:凡是用于完成操作系统的各种功能的进程就是系统进程,他们就是出于运行状态下的操作系统本身
用户进程:运行用户程序时创建的运行在用户态下的进程。
-
进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位。
-
在同一个时间里,同一个操作系统中如果
允许两个或两个以上的进程处于运行状态
,这便是多进程。
5. 多线程:
-
同一时间,CPU 只能处理1条线程,只有1条线程执行。多线程并发执行,其实是CPU快速地在多条线程之间调度(切换)。如果CPU的调度线程的时间足够快,就造成了多线程并发执行的假象。
-
如果线程非常至多(N条),CPU会在这些(N条)线程之间调度,消耗大量的CPU资源,每条线程被调用执行的频率会降低(线程的执行效率降低)。
-
多线程的优点:
-
能适当提高程序的执行效率
-
能适当提高资源的利用率(CPU、内存利用率)
-
-
多线程的缺点:
-
开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512kb),如若开启大量线程,会占用大量的内存空间,就会降低程序的性能
-
线程越多,CPU在调度线程的开销就越大
-
程序设计更加复杂:如线程之间的通信、多线程之间的数据共享等
-
二、iOS开发中有多少类型的线程?分别对比?
NSThread
每个NSThread
对象对应一个线程,量级较轻(真正的多线程)。是对pthread(其是POSIX线程的API,是C语言的技术,当然它可以直接操作线程)的抽象。NSOperation/NSOperationQueue
面向对象的线程技术,是对GCD的抽象,容易理解和使用。GCD —— Grand Central Dispatch(派发)
是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术
对比:
线程类型 | 优点 | 缺点 |
---|---|---|
NSThread | 1. 跨平台C语言标准库中的多线程框架 2. 使用简单 | 1. 过于底层使用很麻烦,需要封装使用。2. 需要自己来管理线程的生命周期 、线程同步 、加锁 、睡眠和唤醒 。过程不可避免的有一定的系统“开销” |
NSOperation / NSOperationQueue | 1. 更加面向对象,可以设置并发数量 ,可以设置优先级 可以设置依赖 ,可以任务执行状态控制 :isReady(是否准备好执行),isExecuting(是否正在执行),isFinished(是否执行完毕),isCancelled(是否被取消) 2. 不用关心线程的管理和数据的同步,把精力放在自己需要执行的任务或操作上就行了 3. GCD 的封装 | 用于相对复杂的场景,相对简单的官方推荐 GCD |
GCD(Grand Central Dispatch) | 1. iOS5后苹果推出的双核CPU优化的多线程框架,iOS 4.0 才能使用,是代替上面两个技术的高效而且强大的技术2. 它基于block的特性导致它能极为简单的在不同代码作用域之间传递上下文,效率高 3. GCD自动根据系统负载来增减线程数量,这就减少了上下文的切换和提高了计算效率 4. 安全,无需加锁或其他同步机制5. 它是基于C语言的 | 1. 不能设置并发数,需要写一些代码曲线方式实现并发 2. 不能设置优先级 |
三、GCD有哪些队列,默认提供哪些队列?
3中队列:主线程队列
、并发队列
、串行队列
在GCD中有两种队列:串行队列
和并发队列
。两者都符合 FIFO
的原则,二者的主要区别是:执行的顺序不同和开启的线程数不同。
1.主线程队列:
main queue
可以调用dispatch_get_main_queue()
来获得。因为main queue
是与主线程相关的,所以这是一个串行队列。和其它串行队列一样,这个队列中的任务一次只能执行一个。它能保证所有的任务都在主线程执行,而主线程是唯一可用于更新 UI 的线程。
2. 串行队列(Serial Dispatch Queue):
同一时间内,队列中只能执行一个任务,只有当前的任务执行完成之后,才能执行下一个任务。(只能开启一个线程,一个线程执行完毕后,再执行下一个任务)。主队列是主线程上的一个串行队列,是系统自动为程序创建的。
3. 并行队列(Concurrent Dispatch Queue):
同时允许多个任务同时执行。(可以开启多个线程,并且同时执行)。并发队列的并发功能只有在异步(dispatch_async)
函数下才有效。
四、GCD有哪些方法 api?
1. Dispatch Queue :
开发者要做的只是定义想执行的任务并追加到适当的 Dispatch Queue
中。
dispatch_async { queue, ^{//想执行的任务});
通过 dispatch_async
函数“追加”赋值在变量 queue
的“Dispatch Queue
中”。
Dispatch Queue 的种类:
有两种Dispatch Queue,一种是等待现在执行中处理的 Serial Dispatch Queue
,另一种是不等待现在执行中处理的 Concurrent Dispatch Queue
。
2. dispatch_queue_create :
创建队列
3. Main Dispatch Queue 和 Global Dispatch Queue :
系统提供的两种队列
4. dispatch_set_target_queue :
变更队列执行的优先级
5. dispatch_after :
延时执行。
注意
的是dispatch_afte
r函数并不是在指定时间后执行处理,而只是在指定时间追加处理到 Dispatch Queue
。
6. dispatch_group :
调度任务组。
dispatch_group_notify
:最后任务执行完的通知,比如:
- (void)dispatch_group {dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{NSLog(@"thread1:%@", [NSThread