美文网首页
1.2、iOS面试题之多线程

1.2、iOS面试题之多线程

作者: zmfflying | 来源:发表于2020-06-14 14:40 被阅读0次

    1.简述GCD,NSThread,NSOperation使用,各自优缺点

    NSThread:

    –优点:NSThread 比其他两个轻量级,使用简单

    –缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销

    NSOperation、GCD:

    优点:不需要关心线程管理,数据同步的事情。

    两者区别:

    NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。

    GCD主要与block结合使用。代码简洁高效

    1. 性能:GCD更接近底层,而NSOperationQueue则更高级抽象,所以GCD在追求性能的底层操作来说,是速度最快的。这取决于使用Instruments进行代码性能分析,如有必要的话

    2. 从异步操作之间的事务性,顺序行,依赖关系。GCD需要自己写更多的代码来实现,而NSOperationQueue已经内建了这些支持

    3. 如果异步操作的过程需要更多的被交互和UI呈现出来,NSOperationQueue会是一个更好的选择。底层代码中,任务之间不太互相依赖,而需要更高的并发能力,GCD则更有优势

    2.GCD底层原理是什么?

    GCD实现原理: GCD有一个底层线程池,这个池中存放的是一个个的线程。之所以称为“池”,很容易理解出这个“池”中的线程是可以重用的,当一段时间后这个线程没有被调用胡话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统自动来维护,不需要我们程序员来维护(看到这句话是不是很开心?)

    而我们程序员需要关心的是什么呢?我们只关心的是向队列中添加任务,队列调度即可。

    如果队列中存放的是同步任务,则任务出队后,底层线程池中会提供一条线程供这个任务执行,任务执行完毕后这条线程再回到线程池。这样队列中的任务反复调度,因为是同步的,所以当我们用currentThread打印的时候,就是同一条线程。

    如果队列中存放的是异步的任务,(注意异步可以开线程),当任务出队后,底层线程池会提供一个线程供任务执行,因为是异步执行,队列中的任务不需等待当前任务执行完毕就可以调度下一个任务,这时底层线程池中会再次提供一个线程供第二个任务执行,执行完毕后再回到底层线程池中。

     这样就对线程完成一个复用,而不需要每一个任务执行都开启新的线程,也就从而节约的系统的开销,提高了效率。在iOS7.0的时候,使用GCD系统通常只能开5~8条线程,iOS8.0以后,系统可以开启很多条线程,但是实在开发应用中,建议开启线程条数:3~5条最为合理。

    3.给定一个网络请求依赖场景,用自己熟悉的方式解决

    4.常用哪种锁?原理是什么

    https://juejin.im/post/5d554410f265da03b21532cd#heading-53

    gcd栅栏  nslock  @synchronized

    5.atomic一定是线程安全的吗?

    用atomic修饰成员变量,会给成员变量的getter 和 setter方法加锁,使访问每次只能进行一个,避免多个线程同时操作成员变量.

    atomic 只负责直接赋值和读取的线程安全,比如数组,直接赋值和读取是安全的,但是添加和移除不在负责权限内,不安全

    6.NSArray如何保证线程安全?

    将数组的写(插入、修改、删除)操作放进队列中dispatch_barrier函数中,这样当进行写的操作时,会先等待前面的读的任务完成后再执行写操作;而且后面的读任务也要等待dispatch_barrier中的写操作执行完成后才会被执行。

    7.开启一条线程的方法?线程可以取消吗?

    NSOperation - (void)cancel; 可取消操作,实质是标记 isCancelled 状态。

    GCDiOS8之后可以调用dispatch_block_cancel来取消(需要注意必须用dispatch_block_create创建dispatch_block_t)定义外部变量,用于标记block是否需要取消

    8.子线程中调用connection方法,为什么不回调?因为没有加入runloop,执行完任务就销毁了,所以没有回调。

    9.那子线程中的autorelease变量什么时候释放?

    10.子线程里面,需要加autoreleasepool吗

    每一个线程创建的时候就会有一个autorelease pool的创建,并且在线程退出的时候,清空整个autorelease pool。(ps:如果在子线程中设置一个循环,autorelease对象确实无法释放)

    https://zhuanlan.zhihu.com/p/26796146

    在子线程你创建了 Pool 的话,产生的 Autorelease 对象就会交给 pool 去管理。如果你没有创建 Pool ,但是产生了 Autorelease 对象,就会调用 autoreleaseNoPage 方法。在这个方法中,会自动帮你创建一个 hotpage(hotPage 可以理解为当前正在使用的 AutoreleasePoolPage,如果你还是不理解,可以先看看 Autoreleasepool 的源代码,再来看这个问题 ),并调用page->add(obj)将对象添加到 AutoreleasePoolPage 的栈中,也就是说你不进行手动的内存管理,也不会内存泄漏啦!StackOverFlow 的作者也说道,这个是 OS X 10.9+和 iOS 7+ 才加入的特性。并且苹果没有对应的官方文档阐述此事,但是你可以通过源码了解。

    11.项目里面遇到过死锁吗?怎么解决?数据库访问本来就是线程安全的,不会造成死锁啊。什么是死锁?

    所谓死锁,通常指有两个线程T1和T2都卡住了,并等待对方完成某些操作。T1不能完成是因为它在等待T2完成。但T2也不能完成,因为它在等待T1完成。于是大家都完不成,就导致了死锁(DeadLock)。

    12.进程和线程的区别?同步异步的区别?串行和并发的区别?

    1、首先是定义

    进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。

    线程:单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。

    2、一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。

    13.线程间通信?

    https://www.jianshu.com/p/aacd3409f14b

    14.GCD的一些常用的函数?(group,barrier,信号量,线程同步)

    15、OC你了解的锁有哪些?在你回答基础上进行二次提问;

    追问一:自旋和互斥对比?

    追问二:用C/OC/C++,任选其一,实现自旋或互斥?口述即可!

    https://www.jianshu.com/p/3a50d1805655

    相关文章

      网友评论

          本文标题:1.2、iOS面试题之多线程

          本文链接:https://www.haomeiwen.com/subject/mwiuohtx.html