底层20:多线程-同步/异步/并发/串行

2020-09-08  本文已影响0人  张无奈

GCD两种常用的函数:

GCD中有2个用来执行任务的函数

用同步的方式执行任务:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

queue:队列

block:任务

用异步的方式执行任务:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

GCD是开源的:https://github.com/apple/swift-corelibs-libdispatch

GCD队列:

并发队列(Concurrent Dispatch Queue):

可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务);

并发功能只有在异步函数下才有效。

串行队列:让任务一个接着一个地执行(一个任务执行完后,再执行下一个任务)

容易混淆的术语:

有4个术语比较容易混淆:同步、异步、并发、串行

同步和异步主要影响:能不能开启新的线程

同步:在当前线程中执行任务,不具备开启新线程的能力。

异步:在新的线程中执行任务,具备开启新线程的能力

并发和串行主要影响:任务的执行方式

并发:多个任务并发(同时)执行

串行:一个任务执行完毕以后,再执行下一个任务(主队列也是一个串行队列)

各种队列的执行效果

死锁实例分析

实例1:

分析:是在主队列中执行,因为是同步并且在viewDidLoad方法中,所以在是在主线程中执行,队列存在先进先出的原则,首先要执行完viewDidLoad方法才能执行任务2,但是任务2又在viewDidLoad方法中,相当于任务2和3相互等待造成死锁。

实例2:

分析:因为在主线程中执行,是串行队列串行执行任务,而异步刚好不要求立马在当前线程同步执行任务,所以打印顺序:执行任务1、执行任务3、执行任务2

实例3:

分析:发现任务3和任务4跟实例1一样。

实例4: 如下只要创建了第二个队列替换,不管是串行还是并发 都不会产生死锁

实例5: 换成并发队列,任务3,4不会等待,并发执行。

总结:使用 sync函数  往 当前串行队列  中添加任务,会卡住当前的串行队列(产生死锁)

分析:全局队列打印地址一样,说明全局队列始终是同一个队列(也可以理解为全局队列相当于是一个全局变量,始终是同一个);后面自行创建的并发队列,地址不一样,说明是不同的队列。

注意:

[self performSelector:@selector(test) withObject:nil afterDelay:.0];的本质是往RunLoop中添加定时器,而子线程默认没有启动runLoop。所以需要手动启动:

[self performSelector:@selector(test) withObject:nil]跟它是不一样的,没有关系到RunLoop,如果它不启动照常打印。

上一篇下一篇

猜你喜欢

热点阅读