@autoreleasepool作用域结束时,是怎么调用AutoreleasePoolPage::pop()的?
来源:6-7 自动释放池相关面试问题

慕设计5599907
2021-06-08
老师,你课上讲在当次runloop即将结束的时候调用AutoreleasePoolPage::pop(),
而我在测试下面代码时发现,每次循环结束,也就是在autoreleasepool作用域外调用AutoreleasePoolPage::pop()也释放内存,1)这个应该怎么理解?
for (int i=0;i<100000;i++) {
@autoreleasepool {
UIImage *image = [UIImage imageNamed:@“pic”];
}
}
2)下面是我的理解,老师看看有什么问题吗?
由于一个runloop代表一个线程,一个autoreleasepool也代表一个线程,所以autoreleasepool作用域内是子线程的runloop,作用域外是主线程的runloop,每循环一次(同时也出了作用域),这个子线程就结束了,然后就调用了AutoreleasePoolPage::pop()
3)那for循环每次调用 @autoreleasepool 时,是不是调用的同一个子线程,如果不是的话,这些字线程的id为什么不一样?
2回答
-
慕工程748436
2023-06-13
第2点根据我的理解有点表述问题"一个runloop代表一个线程,一个autoreleasepool也代表一个线程,所以autoreleasepool作用域内是子线程的runloop,作用域外是主线程的runloop"
1、线程和runloop是一一对应的关系。runloop是依赖线程(调度)存在的。可以只有线程执行任务,也可以开启线程中的runloop。但是不能凭空创建runloop。
2、每个线程中都有对应的自动释放池,但是和runloop一样,无法独立存在。3、ARC中所有对象默认出了作用域后在某个时间就会自动释放,这个就是放在了当前线程的自动释放池。如果当前线程没有开启runloop,则线程任务执行完毕,线程销毁时释放。如果当前线程开启了runloop,则由runloop来维护。runloop在每次循环都会进行一次自动释放池的清理工作(这部分可以了解runloop的原理)。
4、手动代码创建的自动释放池中的对象在}之后被释放。我们手动创建自动释放池表明我们觉得依赖runloop的话,在这次runloop结束之前会攒下太多对象消耗太多内存,所以手动地主动地提前释放掉这部分内存。
5、主线程和主线程的runloop的生命周期与应用程序的生命周期相同。
另外有点不解,按照提问中的代码,并没有涉及线程切换,所以循环中创建自动释放池应该都是当前线程的才对。
理解有误的话,感谢指正00 -
于海
2021-06-08
可以看下autoreleasepool是一个以栈为节点得双向链表,每次push相当于插入一个哨兵对象
00
相似问题