ios多线程同步异步、串行并行队列、死锁

如题所述

第1个回答  2022-07-30
概念:队列只负责任务的调度,而不负责任务的执行,任务是在线程中执行的。(可以理解成任务是放在队列里面的,要被调度到线程中去执行)
特点:队列先进先出,排在前面的任务最先执行。
分类:队列分为串行、并行、主队列、全局队列。

任务的执行是在线程上去执行的。分为同步和异步。

所以就可以分成:串行队列同步执行、串行队列异步执行、并行队列同步执行、并行队列异步执行。

GCD实现原理:
GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,是因为这个“池”中的线程是可以重用的,当一段时间后没有任务在这个线程上执行的话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统自动来维护,不需要我们程序员来维护。
我们只关心的是向队列中添加任务,队列调度即可。

定义:调用方法(viewDidLoad)的队列(主队列)恰好是同步操作(dispatch_sync)所针对的队列(dispatch_get_main_queue)。
示例1:

输出结果:

dispatch_sync 和 dispatch_async 区别:
dispatch_async(queue,block) async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。
dispatch_sync(queue,block) sync 同步队列,dispatch_sync 函数不会立即返回,及阻塞当前线程,等待 block同步执行完成。

以上例子就会死锁,因为viewDidLoad的这个任务是被主队列调用的的,而dispatch_sync不会立即返回,而是先阻塞当前的主线程,直到这个block执行完毕,因为主线程被阻碍了,啥也干不了了(只有一个线程还被阻塞了,就会造成死锁),所以这个block就永远没有机会执行了,所以就会造成死锁。

示例2:

输出结果:

示例2就不会造成死锁,因为dispatch_async会立即返回,所以会先输出3,而异步会创建一个新的线程来执行block块,所以2最后输出。但是2和3的顺序不一定。

示例3:

输出结果:

示例3也不会造成死锁,因为dispatch_sync不会立即返回,而是先阻塞主线程,再将任务2加入到一个全局队列的一个线程上去执行,执行完之后返回到主队列,此时主线程不在阻塞,再继续执行任务3。
示例4:

输出结果:

因为dispatch_async不会等待,所以顺序是1-4-2-3-5或1-2-4-3-5,其中任务1和4是在主线程执行的,而2是在全局队列上被调用的,执行完2之后,会阻塞当前的线程(全局队列上的),紧接着会回到主队列上的主线程上执行任务3,任务3执行完之后,会继续执行5,此时全局队列上的线程也不堵塞了。

注意:线程同步阻塞后不一定能造成死锁,还要看看还有没有其他线程去执行那个block,如果能有,就能解锁阻塞的线程,继续执行任务。如果没有,那就是死锁了。

示例5:

输出结果:

最终结果还是会导致死锁,因为dispatch_queue_create创建队列的时候传入NULL默认是串行队列,所以执行任务2之后,会阻塞掉当前线程,直到任务3的block执行完成,又因为当前线程被阻塞掉了,block也无法执行,导致相互等待造成死锁

示例6:

输出结果:>=5
因为self.num++操作是异步的,不一定能立马返回结果,所以在进入下次while循环的时候,self.num(主线程)可能还是0,所以循环肯定至少5次,最理想的情况下,5次全部都返回结果,而NSLog是会等待异步结果返回才会打印,所以输出结果>=5

示例7:

输出结果为:<1000
因为总共循环1000次,并不是每次结果都有返回,所以最终打印的self.num肯定小于1000

参考链接
相似回答
大家正在搜