atomic和weak的实现机制(原理)

226 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

atomic的实现机制

  • atomicproperty的修饰词之一,表示是原子性的,使用方法为@property(atomic)int age;此时编译器会自动生成getter/setter方法,最终会调用objc_getPropertyobjc_setProperty方法来进行存取属性。
  • 若此时属性用atomic修饰的话,在这两个方法内部使用os_unfair_lock来进行加锁,来保证读写的原子性。锁都在PropertyLocks中保存着(在iOS平台会初始化8个,mac平台会初始化64个),在用之前,会把锁都初始化好,在需要用到时,用对象的地址加上成员变量的偏移量为key,去PropertyLocks中去取。因此存取时用的是同一个锁,所以atomic能保证属性的存取是线程安全的。
  • 因为锁是有限的,不同对象,不同属性的读取用的可能是同一个锁

atomic不能保证绝对的线程安全

  • atomicgetter/setter方法中加锁,仅保证了存取时的线程安全,假设我们的属性是@property(atomic)NSMutableArray *array;可变的容器时,无法保证对容器的的修改是线程安全的。
  • 在编译器自动生成的getter/setter方法,最终会调用objc_getPropertyobjc_setProperty方法存取属性,在此方法内部保证了读写时的线程安全的,当我们重写getter/setter方法时,就只能依靠自己在getter/setter中保证线程安全。

weak修饰的对象释放则自动被置为nil的实现原理

Runtime维护了一个weak表,存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表Key是所指对象的地址Value是weak指针的地址数组(这个地址的值是所指对象的地址)

weak的实现原理可以概括为以下三步:

  • 1.初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址
  • 2.添加引用时:objc_initWeak函数会调用objc_storeWeak()函数,objc_storeWeak()的作用是更新指针指向,创建对应的弱引用表
    1. 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。