iOS 底层 - 多线程之atomic

2020-04-13  本文已影响0人  水中的蓝天

本文源自本人的学习记录整理与理解,其中参考阅读了部分优秀的博客和书籍,尽量以通俗简单的语句转述。引用到的地方如有遗漏或未能一一列举原文出处还望见谅与指出,另文章内容如有不妥之处还望指教,万分感谢 !

atom: 原子,不可再分割的单位
atomic: 原子操作
nonatomic: 非原子操作

关于atomic

为什么使用nonatomic

objc-accessors.m源码


//加锁方案 os_unfair_lock
using spinlock_t = mutex_tt<LOCKDEBUG>;

template <bool Debug>
class mutex_tt : nocopy_t {
    os_unfair_lock mLock;
 public:
    void lock() {
        lockdebug_mutex_lock(this);

        os_unfair_lock_lock_with_options_inline
            (&mLock, OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION);
    }

    void unlock() {
        lockdebug_mutex_unlock(this);

        os_unfair_lock_unlock_inline(&mLock);
    }
};

散列表
StripedMap<spinlock_t> PropertyLocks;

static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
    if (offset == 0) {
        object_setClass(self, newValue);
        return;
    }

    id oldValue;
    //slot: 属性内存地址
    id *slot = (id*) ((char*)self + offset);

    if (copy) {
        newValue = [newValue copyWithZone:nil];
    } else if (mutableCopy) {
        newValue = [newValue mutableCopyWithZone:nil];
    } else {
        if (*slot == newValue) return;
        newValue = objc_retain(newValue);
    }

    if (!atomic) {//是nonatomic属性
        oldValue = *slot;
        *slot = newValue;
    } else {//是atomic属性,就对赋值过程进行加锁
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock(); //加锁
        oldValue = *slot;
        *slot = newValue;        
        slotlock.unlock();//解锁
    }

    objc_release(oldValue);
}

//设置属性值
void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy) 
{
    bool copy = (shouldCopy && shouldCopy != MUTABLE_COPY);
    bool mutableCopy = (shouldCopy == MUTABLE_COPY);
    reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy);
}


//获取属性值
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (offset == 0) {
        return object_getClass(self);
    }

    // Retain release world
    id *slot = (id*) ((char*)self + offset);
    if (!atomic) return *slot; //是nonatomic属性,直接返回属性地址
        
    // Atomic retain release world  是atomic属性,就对取值过程进行加锁
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock(); //加锁
    id value = objc_retain(*slot);
    slotlock.unlock();//解锁
    
    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    return objc_autoreleaseReturnValue(value);
}
上一篇下一篇

猜你喜欢

热点阅读