iOS 进阶 - 内存管理(三) -- 数据结构

思维导图

iOS 进阶 - 内存管理(三) -- 数据结构

概述

iOS 进阶 - 内存管理(三) -- 数据结构

  • 内存布局(iOS 系统下的内存布局是什么样的?)
  • 内存管理方案(iOS操作系统是怎么对内存进行管理的?)
  • 数据结构(更好的讲述内存管理方案相关的问题,就要明白他们的数据结构)
  • ARC&MRC(什么是ARC,什么是MRC,他们的区别以及各自实现的机制、原理)
  • 引用计数机制(什么是引用计数机制?内存是怎样管理的?)
  • 弱引用表(我们声明weak的一个变量,为什么在内存释放的时候,weak指针会自动置为nil?弱引用变量内存是怎么管理的?)
  • 自动释放池(AutoReleasePool)的实现机制和原理是怎样的?
  • 循环引用(常考点和易错点,考察对内存管理理解的深度)

数据结构(散列表)

有关散列表实现的内存管理方案涉及到的一些数据结构

自旋锁Spinlock_t

你是否使用过自旋锁,自旋锁和普通锁有什么区别,自旋锁有哪些使用场景呢?

  • 是一种"忙等"的锁,如果当前锁已被其他线程获取,当前线程会不断探测这个锁有没有被释放,如果被释放了,线程就会第一时间去获取这个锁。
  • 比如说其他的锁,比如信号量,当它获取不到这个锁时,会把自己的线程进行阻塞休眠,然后等到其他线程释放这个锁的时候,再唤醒当前线程
  • 自旋锁适用于轻量访问。(比如说上面Side Table表,如果说我们对某一个对象来进行引用计数操作的话,来访问这个表,
    实际上做+1-1操作是非常快的操作,那么我们可以把它定义为轻量访问。我们在这种轻量访问的场景下,可以使用自旋锁。)
引用计数表RefcountMap

iOS 进阶 - 内存管理(三) -- 数据结构

  1. 引用计数表是哈希表,可以理解为是一个字典,可以通过指针,找到对应对象的引用计数,这个查找过程是一个哈希查找。
  2. 这个哈希算法实际上是对传入对象的指针做一个伪装的操作,然后去获取对应的引用计数(size_t)
  3. 之所以使用哈希查找,是为了提高查找效率。
  4. size_t表达的就是对象的引用计数值,是一个无符号long型的变量

查找效率的提高,是因为我们存储一个对象的引用计数时,是通过同一个函数来计算存储位置的,而获取对象的引用计数值的时候,也通过同一个函数来计算应该获取的索引位置,因为插入和获取都是通过同一个函数来计算位置,就会避免循环遍历的操作。所以才说,哈希查找可以提高查找效率。

size_t每一个bit为代表的含义
iOS 进阶 - 内存管理(三) -- 数据结构
假如引用计数存储是用64位来表示的

  • 第1个二进制位(weakly_referenced)表示对象是否有弱引用
  • 第2位(deallocating)表示当前对象是否正在delloc
  • 其他(RC)存储这个对象的实际引用计数值
  • 当我们计算对象的引用计数时,需要对这个值进行向右偏移两位,因为要去掉后面两位,才可以取到真实的引用计数值
弱引用表weak_table_t

iOS 进阶 - 内存管理(三) -- 数据结构

  • 在Runtime源码中可以看到,弱引用表示根据weak_table_t来定义的,weak_table_t也是一张哈希表,给与一个对象的指针作为key,通过一个哈希函数,就可以计算出对应的弱引用的对象的存储位置。
  • weak_entry_t实际上也是一个结构体数组,这个数组中存储的每一个对象就是实际的弱引用指针,也就是我们在代码当中定义的类似于__weak id obj,那么这个obj内存地址或者说这个指针就存储在weak_entry_t这个结构体数组中。