1、atomic简介
atomic用于保证属性setter、getter的原子性操作,相当于在getter和setter内部加了线程同步的锁,可以通过 objc源码 中的objc-accessors.mm文件查看:
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
......
if (!atomic) {// 非原子
oldValue = *slot;
*slot = newValue;
} else {// 原子
spinlock_t& slotlock = PropertyLocks[slot];
// 加锁
slotlock.lock();
oldValue = *slot;
*slot = newValue;
// 解锁
slotlock.unlock();
}
......
}
在执行属性的set方法时,如果是非原子就直接赋值,如果是原子就会进行加锁解锁操作。属性的get方法原理相同:
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
if (offset == 0) {
return object_getClass(self);
}
id *slot = (id*) ((char*)self + offset);
if (!atomic) return *slot; //非原子:直接返回
// 原子:加锁、解锁
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
id value = objc_retain(*slot);
slotlock.unlock();
return objc_autoreleaseReturnValue(value);
}
2、atomic特点
2.1、不能保证属性使用过程的线程安全
比如person有一个data属性,外部可以不通过set/get方法去修改data,所以data也不是完全安全的。
Person *person = [[Person alloc] init];
// 线程安全,调用set/get方法
person.data = [[NSMutableArray alloc] init];
// 线程不安全,直接修改属性内容
[person.data addObject:@"1"];
[person.data addObject:@"2"];
[person.data addObject:@"3"];
2.2、性能消耗比较大
对象属性的调用频率比较大,如果使用automic会频繁创建自旋锁,多内存和CPU消耗多比较大。所以iOS中一般不使用aotomic,如果要保证同步可以再需要同步的地方手动加锁。