1、atomic简介

atomic用于保证属性setter、getter的原子性操作,相当于在getter和setter内部加了线程同步的锁,可以通过 objc源码 中的objc-accessors.mm文件查看:

  1. static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
  2. {
  3. ......
  4. if (!atomic) {// 非原子
  5. oldValue = *slot;
  6. *slot = newValue;
  7. } else {// 原子
  8. spinlock_t& slotlock = PropertyLocks[slot];
  9. // 加锁
  10. slotlock.lock();
  11. oldValue = *slot;
  12. *slot = newValue;
  13. // 解锁
  14. slotlock.unlock();
  15. }
  16. ......
  17. }

在执行属性的set方法时,如果是非原子就直接赋值,如果是原子就会进行加锁解锁操作。属性的get方法原理相同:

  1. id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
  2. if (offset == 0) {
  3. return object_getClass(self);
  4. }
  5. id *slot = (id*) ((char*)self + offset);
  6. if (!atomic) return *slot; //非原子:直接返回
  7. // 原子:加锁、解锁
  8. spinlock_t& slotlock = PropertyLocks[slot];
  9. slotlock.lock();
  10. id value = objc_retain(*slot);
  11. slotlock.unlock();
  12. return objc_autoreleaseReturnValue(value);
  13. }

2、atomic特点

2.1、不能保证属性使用过程的线程安全

比如person有一个data属性,外部可以不通过set/get方法去修改data,所以data也不是完全安全的。

  1. Person *person = [[Person alloc] init];
  2. // 线程安全,调用set/get方法
  3. person.data = [[NSMutableArray alloc] init];
  4. // 线程不安全,直接修改属性内容
  5. [person.data addObject:@"1"];
  6. [person.data addObject:@"2"];
  7. [person.data addObject:@"3"];

2.2、性能消耗比较大

对象属性的调用频率比较大,如果使用automic会频繁创建自旋锁,多内存和CPU消耗多比较大。所以iOS中一般不使用aotomic,如果要保证同步可以再需要同步的地方手动加锁。