美文网首页
避免误区!atomic的线程安全问题。

避免误区!atomic的线程安全问题。

作者: 我是繁星 | 来源:发表于2018-09-13 19:58 被阅读0次

    背景

    我们日常,在我们的印象中原子性是和线程安全划等号的,事实确实是这样的,不要被一些标题党误导😂,说他不是线程安全是相对于整个对象的。

    概念

    维基百科的解释:线程安全是指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程,使程序功能正确完成。其实意思就是多线程情况下程序的执行顺序要有单一性和正确性。

    原子性:关于原子性可以看下这篇文章《关于原子性的理解》
    概括一下原子性就是保证一个操作的完整性(不可被打断),在我们oc中就是保证setter和getter操作的完整性。

    结论:

    那我们的结论是这样的:
    用atomic修饰后,这个属性的setter、getter方法是线程安全的,但是对于整个对象来说不一定是线程安全的。

    原因:

    1.为什么setter、getter方法是线程安全的?

    因为在setter和getter赋值取值的时候添加了自旋锁,不懂看这《oc中的线程锁》

    // 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没办法保证整个对象的线程安全,这里主要看一下网上主流的答案?

    1.对于NSArray类型 @property(atomic)NSArray *array我们用atomic修饰,数组的添加和删除并不是线程安全的,这是因为数组比较特殊,我们要分成两部分考虑,一部分是&array也就是这个数组本身,另一部分是他所指向的内存部分。atomic限制的只是&array部分,对于它指向的对象没有任何限制。
    atomic表示,我TM也很冤啊!!!!

    2.当线程A进行写操作,这时其他线程的读或者写操作会因为该操作而等待。当A线程的写操作结束后,B线程进行写操作,然后当A线程需要读操作时,却获得了在B线程中的值,这就破坏了线程安全,如果有线程C在A线程读操作前release了该属性,那么还会导致程序崩溃。所以仅仅使用atomic并不会使得线程安全,我们还要为线程添加lock来确保线程的安全。
    个人觉得这个就有点杠精的意味了,atomic还要管到你方法外面去了?????不过面试人家问你还要这么答,要严谨!!

    相关文章

      网友评论

          本文标题:避免误区!atomic的线程安全问题。

          本文链接:https://www.haomeiwen.com/subject/ohhwgftx.html