iOS 屬性修飾符atomic的內(nèi)部實現(xiàn)是怎么樣的?能保證線程安全嗎?
1、內(nèi)部實現(xiàn)
在 objc4-723 的 Objective-C runtime 實現(xiàn)中,property 的 atomic 是采用 spinlock_t 也就是俗稱的自旋鎖實現(xiàn)的。
// 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 在執(zhí)行表達式 self.intA之后 self.intA = self.intA + 1;并沒有執(zhí)行完畢
此時threadB 執(zhí)行self.intA = self.intA + 1;
再回到threadA時,self.intA的數(shù)值就被更新了
所以僅僅使用atomic并不能保證線程安全。