先说说什么是线程不安全?
由多线程访问和修改共享资源造成的不可预测的结果叫做线程不安全。
如何避免线程不安全?
通常利用给共享资源加锁来保证线程安全。加锁是一种操作,线程安全是利用锁来构建的一种代码模式,不可混为一谈。加锁的对象或者范围,决定是否线程安全。
atomic 是什么?
Objective-c 中 atomic 和 nonatomic 是用来修饰属性,atomic (原子性)修饰的属性,get/set 方法 会被加锁(slotlock.lock),保证了读写的线程安全。nonatomic 则没有加锁操作,效率更高。
// getter
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
// ...
if (!atomic) return *slot;
// Atomic retain release world
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
id value = objc_retain(*slot);
slotlock.unlock();
// ...
}
// 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();
}
// ...
}
为什么说 atomic 不能保证线程安全 ?
举例1. atomic 对get/set加锁,只能保证属性读写的安全,并不保证属性的线程安全。
举例2. atomic 修饰的属性是一个对象,比如NSArray,只能保证NSArray的地址的get/set的读写安全,而对NSArray的其他操作,比如 add/remove 需要调用方去加锁才能保证线程安全。