iOS中常见的多线程方案(后面三个的底层都是基于pthread) |
||||
技术方案 |
简介 |
语言 |
线程生命周期 |
使用频率 |
pthread |
- 一套通用的多线程API - 适用于Unix/Linux/Windows等系统 - 跨平台/可移植 - 使用难度大 |
C |
程序员管理 |
几乎不用 |
NSThread |
- 使用更加面向对象 - 简单易用,可直接操作线程对象 |
OC |
程序员管理 |
偶尔使用 |
GCD |
- 旨在替代NSThread等线程技术 - 充分利用设备的多核 |
C |
自动管理 |
经常使用 |
NSOperation |
- 基于GCD(底层是GCD) - 比GCD多了一些更简单实用的功能 - 使用更加面向对象 |
OC |
自动管理 |
经常使用 |
GCD的常用函数 GCD中有2个用来执行任务的函数 1、用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); - queue:队列 - block:任务 2、用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block); GCK源码:https://github.com/apple/swift-corelibs-libdispatch
GCD的队列 GCD的队列可以分为2大类型 1、并发队列(Concurrent Dispatch Queue) - 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务) - 并发功能只有在异步(dispatch_async)函数下才有效 2、串行队列(Serial Dispatch Queue) - 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
容易混淆的术语 有4个术语比较容易混淆:同步、异步、并发、串行 1、同步和异步主要影响:能不能开启新的线程 - 同步:在当前线程中执行任务,不具备开启新线程的能力 - 异步:在新的线程中执行任务,具备开启新的线程的能力 2、并发和串行主要影响:任务的执行方式 - 并发:多个任务并发(同时)执行 - 串行:一个任务执行完毕后,再执行下一个任务
并发队列 |
手动创建的串行队列 |
主队列 |
|
同步(sync) |
- 没有开启新线程 - 串行执行任务 |
- 没有开启新线程 - 串行执行任务 |
- 没有开启新线程 - 串行执行任务 |
异步(async) |
- 有开启新线程 - 并发执行任务 |
- 有开启新线程 - 串行执行任务 |
- 没有开启新线程 - 串行执行任务 |
- 使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁)
- 主队列其实也是一个串行队列,(queue:队列)
- dispatch_sync:立马在当前线程执行任务,执行完毕后才能继续往下执行
- (void)viewDidLoad { [super viewDidLoad]; //问题:以下代码是在主线程执行的,会不会产生死锁?会! NSLog(@"执行任务1"); //队列的特点:排队,FIFO: First In First Out,先进后出。 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"执行任务2"); }); //dispatch_sync: 立马在当前线程执行任务,执行完毕后才能继续往下执行 NSLog(@"执行任务3"); }
- (void)viewDidLoad { [super viewDidLoad]; //问题:以下代码是在主线程执行的,会不会产生死锁?不会! NSLog(@"执行任务1"); //队列的特点:排队,FIFO: First In First Out,先进后出。 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"执行任务2"); }); //dispatch_async: 不要求立马在当前线程同步执行任务 NSLog(@"执行任务3"); }
并发队列:系统创建的:dispatch_get_global_queue(0, 0):这是全局并发队列是系统创建好的并发队列可以直接调用,你也可以自己创建并发队列或者串行队列。全局并发队列只有一个,也就是不管你调用多少次都是同一个,指针地址都是一样的。但是自己创建的并发队列是不同的
并发队列:自己创建的:dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
串行队列:自己创建的:dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
死锁:并发队列里面不管有多少个任务都可以同时执行,不存在谁等谁的问题
串行队列里面如果有多个任务必须要等前一个任务执行完才能执行后一个任务,所以如果后一个任务包含前一个任务的一部分,那么就会产生死锁。因为前一个任务里有一部分在第二个任务所以要去执行第二个任务,但是第二个任务必须等前一个任务执行完才能执行,所以你等我我等你就造成了死锁。
总结:使用sync函数往当前串行队列中添加任务,会卡住当前串行队列(产生死锁)。