原子属性,只能保证getter
、setter
的操作是安全的。我们看下objc
里关于getter
、setter
的实现。
//objc-accessors.mm
///属性锁
static StripedMap<spinlock_t> PropertyLocks;
/// getter
id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
id *slot = (id*) ((char*)self + offset);
if (!atomic) return *slot;
//原子,使用自旋锁加锁
// Atomic retain release world
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
id value = objc_retain(*slot);
slotlock.unlock();
return objc_autoreleaseReturnValue(value);
}
///setter
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();
}
objc_release(oldValue);
}
可以看到标记atomic
的property
生成的getter
、setter
内部使用了spinlock_t
自旋锁保证了getter
、setter
的访问安全。
这里的
spinlock_t
并不是真正的自旋锁,iOS 10以后,底层换成了os_unfair_lock
。
atomic
原子特性并非绝对的线程安全,在其他复杂多线程操作环境依然会有问题。比如说多线程进行Array
的add
、remove
操作,并不能保证add
、remove
顺序执行,所以会有安全问题。建议还是自己使用lock
加锁保证线程安全。