iOS Atomic 底层分析

1,583 阅读1分钟

原子属性,只能保证gettersetter的操作是安全的。我们看下objc里关于gettersetter的实现。

//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);
}

可以看到标记atomicproperty生成的gettersetter内部使用了spinlock_t自旋锁保证了gettersetter的访问安全。

这里的spinlock_t并不是真正的自旋锁,iOS 10以后,底层换成了os_unfair_lock

atomic原子特性并非绝对的线程安全,在其他复杂多线程操作环境依然会有问题。比如说多线程进行Arrayaddremove操作,并不能保证addremove顺序执行,所以会有安全问题。建议还是自己使用lock加锁保证线程安全。

参考链接

opensource objc4