美文网首页
weak为什么能够避免循环引用,底层是如何实现的

weak为什么能够避免循环引用,底层是如何实现的

作者: 没八阿哥的程序 | 来源:发表于2024-08-12 17:50 被阅读0次

weak引用能够避免循环引用的关键在于它不会增加引用计数(Reference Count),从而打破对象之间的强引用循环,避免内存泄漏。为了理解这个过程,需要深入探讨weak引用的底层实现及其在内存管理中的作用。

循环引用问题

在iOS中,ARC(Automatic Reference Counting)管理对象的内存。当一个对象被另一个对象强引用时(通过strong引用),它的引用计数会增加1。当引用计数变为0时,ARC会自动释放该对象的内存。

假设A对象强引用B对象,B对象又强引用A对象,这种情况下,由于两个对象互相强引用,即使它们已经不再被其他对象引用,ARC也无法将它们的引用计数减少到0,导致它们无法被释放,造成内存泄漏。这就是循环引用。

weak引用如何避免循环引用

weak引用与strong引用的不同在于:当我们用weak声明一个引用时,它不会增加对象的引用计数。因此,如果A对象弱引用B对象,而B对象强引用A对象,那么当A对象被释放后,B对象的引用计数也会减少到0并被释放。这样,循环引用就被打破了。

weak引用的实现原理

weak引用的底层实现涉及到Objective-C runtime的一些机制,特别是objc_storeWeakobjc_release这两个函数。以下是weak引用的工作流程:

  1. 注册弱引用:当一个对象通过weak引用被引用时,Objective-C runtime会在全局的弱引用表(weak table)中记录该对象的内存地址以及所有指向它的weak指针。这个表格类似于一个哈希表,键是被引用对象的内存地址,值是所有指向它的weak指针。
  2. 对象销毁时更新弱引用:当一个对象的引用计数减少到0并且ARC决定销毁该对象时,Objective-C runtime会在对象的析构函数中,首先查找该对象在弱引用表中的记录,然后将所有指向该对象的weak指针置为nil。这就确保了weak指针在对象被释放后不会再指向无效的内存地址。
  3. 线程安全性:为了保证在多线程环境下的安全,weak表的操作是线程安全的。当多个线程同时操作同一个弱引用时,Objective-C runtime会确保这些操作不会导致数据竞态问题。

objc_storeWeak 函数

objc_storeWeak是用来设置weak引用的函数。在weak引用被设置时,它会:

检查当前的弱引用是否已经存在于弱引用表中,如果存在,直接返回。
如果不存在,将新的weak引用添加到弱引用表中,并指向对应的对象。
如果目标对象已经被释放,则将weak引用设置为nil,确保它不会指向一块无效的内存。

objc_release 函数

objc_release函数负责减少对象的引用计数,并在对象引用计数为0时触发对象的析构函数。在对象被销毁时,ARC会调用objc_release函数来处理引用计数的递减。与此同时,弱引用表会被查询和更新,所有指向该对象的weak指针都会被置为nil

weak引用的优缺点

  • 优点:
    • weak引用有效地解决了循环引用问题,避免了内存泄漏。
    • 它自动处理指向已销毁对象的指针,将其设置为nil,从而避免了野指针(dangling pointer)的问题。
  • 缺点:
    • weak引用比strong引用稍微慢一些,因为它涉及到弱引用表的查找和更新操作。
    • weak引用的使用场景有限,主要用于避免循环引用或在多个地方引用同一个对象时,确保不会阻止对象的释放。

总结

weak引用之所以能够避免循环引用,是因为它不会增加对象的引用计数,从而允许对象在没有其他强引用时被正常释放。其底层实现依赖于Objective-C runtime的弱引用表,通过这个表的查找和更新,确保weak指针在目标对象销毁后不会再指向无效的内存地址。通过这种机制,weak引用为开发者提供了一种安全、有效的方式来管理内存,特别是在避免循环引用方面表现尤为出色。

相关文章

  • 你真的懂 weak strong dance 吗?

    在阅读这篇文章之前,首先思考如下问题: 为什么 weak strong dance 能够避免循环引用? 为什么不直...

  • weak

    weak的底层实现weak 弱引用的实现方式

  • __weak与__block的区别

    1.由上篇文章,已经了解到,weak是可以避免循环引用的,那么__weak的作用是什么呢,答案是:也是避免循环引用...

  • 【iOS】weak的底层实现

    转载自:【iOS】weak的底层实现 weak底层千千万,吾竟装作看不见... weak基本用法 weak是弱引用...

  • self 在 block 里面的三种不同情况

    self 的循环引用 当使用代码块和异步分发的时候,要注意避免引用循环。 总是使用 weak 来引用对象,避免引用...

  • Block中self的循环引用--摘自《禅与 Objective

    ### self的循环引用 当使用代码块和异步分发的时候,要注意避免引用循环。总是使用`weak`来引用对象,避免...

  • iOS面试重点

    [TOC] 一 属性 快速问答 delegate 属性为什么使用 weak ?是为了避免循环引用 xib/stor...

  • block3

    Block循环引用 没有调用dealloco 持有blk_blk_持有o, __weak避免循环引用 也可以用__...

  • Weak解读

    在常规开发中我们经常使用__weak修饰符来修饰一个对象,来解决比如循环引用问题.今天具体来看看weak底层实现原...

  • 深入理解 weak-strong dance

    weak-strong dance 简介 使用 Block 时可以通过__weak来避免循环引用已经是众所周知的事...

网友评论

      本文标题:weak为什么能够避免循环引用,底层是如何实现的

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