小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
atomic的实现机制
atomic
是property
的修饰词之一,表示是原子性的
,使用方法为@property(atomic)int age
;此时编译器会自动生成getter/setter
方法,最终会调用objc_getProperty
和objc_setProperty
方法来进行存取属性。- 若此时属性用
atomic
修饰的话,在这两个方法内部使用os_unfair_lock
来进行加锁,来保证读写的原子性。锁都在PropertyLocks
中保存着(在iOS平台会初始化8个,mac平台会初始化64个),在用之前,会把锁都初始化好,在需要用到时,用对象的地址加上成员变量的偏移量为key,去PropertyLocks
中去取。因此存取时用的是同一个锁,所以atomic能保证属性的存取是线程安全的。 - 因为锁是有限的,不同对象,不同属性的读取用的可能是同一个锁
atomic不能保证绝对的线程安全
atomic
在getter/setter
方法中加锁,仅保证了存取时的线程安全
,假设我们的属性是@property(atomic)NSMutableArray *array;
可变的容器时,无法保证对容器的的修改是线程安全的。- 在编译器自动生成的
getter/setter
方法,最终会调用objc_getProperty
和objc_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()
的作用是更新指针指向
,创建对应的弱引用表
。 -
- 释放时,调用
clearDeallocating
函数。clearDeallocating
函数首先根据对象地址获取所有weak
指针地址的数组,然后遍历这个数组把其中的数据设为nil
,最后把这个entry从weak表中删除,最后清理对象的记录。
- 释放时,调用