说说那些年不懂的atomic和nonatomic的区别

博客探讨了Objective-C中属性声明的atomic和nonatomic的区别。atomic提供一定程度的线程安全性,保证了setter和getter操作的原子性,但速度较慢。nonatomic则不保证线程安全,速度较快。虽然atomic在setter/getter中使用了锁,但在现代iOS系统中,其性能与nonatomic相近。在不需要多线程同步的情况下,nonatomic通常用于优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,明确几个概念,原子性是什么?线程安全是什么?原子性是指一个事物的操作是不可分割的,要么都发生,要么都不发生。线程安全是指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程,使程序功能正确完成。其实意思就是多线程情况下程序的执行顺序要有单一性和正确性。

atomic 原子属性

  • 是默认的
  • 只能说是set/get是安全的,但当进行其他操作的时候,线程并不是完全安全的
  • 会保证 CPU 能在别的线程来访问这个属性之前,先执行完当前流程
  • 速度不快,因为要保证操作整体完成
  • set/get方法内部加锁

nonatomic 非原子属性

  • 不是默认的
  • 线程不安全
  • 如有两个线程访问同一个属性,会出现无法预料的结果
  • 更快
  • set/get方法都不会加锁

苹果底层是atomic的setter/getter是os_unfair_lock,差点被苹果骗了!原来系统中自旋锁已经全部改为互斥锁实现了,只是名称一直没有更改。为了修复优先级反转的问题,苹果也只能放弃使用自旋锁,改用优化了性能的 os_unfair_lock,实际测试两者的效率差不多。

(各类锁可以参考https://www.jianshu.com/p/938d68ed832c

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

using spinlock_t = mutex_tt<LOCKDEBUG>;
using mutex_t = mutex_tt<LOCKDEBUG>;

class mutex_tt : nocopy_t {
    os_unfair_lock mLock; //处理了优先级的互斥锁
    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);
    }
}

注:atomic是Objc使用的一种线程保护技术,基本上来讲是防止在写未完成的时候另一个线程读取,造成的数据错误。而这种机制是非常耗费系统资源的,所以iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。而iOS开发中,普遍使用nonatomic也是基于性能这一点。

也可以看看这https://stackoverflow.com/questions/588866/whats-the-difference-between-the-atomic-and-nonatomic-attributes大佬们的理解!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值