iOS 属性修饰符atomic的内部实现是怎么样的?能保证线程安
2018-01-18 本文已影响17人
Pandakingli
iOS 属性修饰符atomic的内部实现是怎么样的?能保证线程安全吗?
1、内部实现
在 objc4-723 的 Objective-C runtime 实现中,property 的 atomic 是采用 spinlock_t 也就是俗称的自旋锁实现的。
// 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();
}
// ...
}
2、能否保证线程安全?
atomic通过这种方法,在运行时保证 set,get方法的原子性。
仅仅是保证了set,get方法的原子性。
这种线程是不安全的。
@property (atomic, assign) int intA;
//线程A
for (int i = 0; i < 10000; i ++)
{
self.intA = self.intA + 1;
NSLog(@"Thread A: %d\n", self.intA);
}
//线程B
for (int i = 0; i < 10000; i ++)
{
self.intA = self.intA + 1;
NSLog(@"Thread B: %d\n", self.intA);
}
self.intA 是原子操作,但是self.intA = self.intA + 1这个表达式并不是原子操作。
所以线程是不安全的。
threadA 在执行表达式 self.intA之后 self.intA = self.intA + 1;并没有执行完毕
此时threadB 执行self.intA = self.intA + 1;
再回到threadA时,self.intA的数值就被更新了
所以仅仅使用atomic并不能保证线程安全。