《新浪微博剖析 iOS 高级面试》笔记(六):多线程相关面试问题
GCD
1、同步/异步 & 串行/并发
a、同步串行

b、死锁原因

- 死锁是因为队列引起的循环等待,而非线程。
- 首先在
主线程执行主队列中的viewDidLoad函数。 - 当执行到
block时,因为是同步,所以需要hold住主线程中主队列正在执行的viewDidLoad函数,等执行完主队列中block内部代码后,再执行主线程中主队列的viewDidLoad函数。 - 所以出现了
viewDidLoad等待block的情况。 block内的代码要执行,必须等待队列中其他函数执行完,即先进先出。- 所以出现了
block等待viewDidLoad的情况。 - 最终两个函数
相互等待,出现造成死锁。
- 首先在
- 上面这种用法没问题
- 首先在
主线程执行主队列中的viewDidLoad函数。 - 当执行到
block时,因为是同步,所以需要hold住主线程中主队列正在执行的viewDidLoad函数,等执行完主队列中block内部代码后,再执行主线程中主队列的viewDidLoad函数。 - 所以出现了
viewDidLoad等待block的情况。 block内部的代码会在serialQueue的队列中取出,因为serialQueue中block排在最前,所以block会被立即取出,并在主线程中执行。- 待
block执行完毕,会执行viewDidLoad剩余代码。
- 首先在

- 因为是
并发队列,所以运行队列中的任务一起执行,不需要等待上一个任务执行完再执行下一个,所以不会死锁。 - 如果
global_queue换成串行队列,就会产生死锁。
c、异步串行

- 先执行完
viewDidLoad,再执行block内的代码。
- 因为子线程默认没有开启
runloop,performSelector无法执行。
2、dispatch_barrier_async
a、怎样利用GCD实现多读单写?

- 读的时候使用
dispatch_sync,是因为使用同步队列可以在赋值结束后,再执行返回值的操作。
3、dispatch_group
a、使用GCD实现A、B、C三个任务并发,完成后执行任务D。

NSOperation
1、优势、特点
- 添加任务依赖
- 任务执行状态控制
- 最大并发量
2、任务状态
isReadyisExecutingisFinishedisCancelled
3、任务状态控制
- 如果只重写
main方法,底层控制变更任务执行完成状态,以及任务退出。 - 如果重写了
start方法,自行控制任务状态。
a、系统是怎样移除一个isFinished=YES的NSOperation的?
- KVO
NSThread
1、NSThread启动流程

多线程与锁
- os_unfair_lock
- OSSpinLock
- 循环等待询问,不释放当前资源
- 用于轻量级数据访问,简单的int值 +1/-1操作
- dispatch_semaphore
- pthread_mutex
- dispatch_queue(DISPATCH_QUEUE_SERIAL)
- NSLock
- NSCondition
- pthread_mutex(recursive)
- NSRecursiveLock
- NSConditionLock
- @synchronized
- 一般在创建单例对象的时候使用,保证在多线程环境下,创建是唯一的。
1、NSLock死锁问题

- 可以使用
NSRecursiveLock递归锁来解决该问题。
多线程面试问题总结
- 怎样用
GCD实现多读单写? - iOS系统为我们提供的几种多线程技术各自的特点是怎样的?
AFNetworking&SDWebImage使用NSOperation,因为可以控制线程状态。
- 系统是怎样移除一个
isFinished=YES的NSOperation的? - 你都用过哪些锁?结合实际谈谈你是怎样使用的?
转载自:https://juejin.cn/post/6901562047965134861