OC 基础之atomic和nonatomic关键字

开聊

在iOS开发中,一般状况下,一个类可能会有多个属性,而用来修饰属性的关键字有不少,咱们也会常常遇到下面的面试题:程序员

  • atomicnonatomic均可以用来修饰一个属性,为何iOS开发中一般用nonatomic修饰属性?atomic是线程安全的吗(最好结合场景聊聊)?
@property (copy) NSString *name;
@property (atomic, copy) NSString *name;
@property (nonatomic, copy) NSString *name;
复制代码
  • 以上3行代码有什么区别? 答:若是是编译器自动生成getter和setter方法,第一、2行代码没有任何区别(缺省的关键字即atomic),第3行代码和前2行代码不一样。若是是咱们手动实现getter和setter方法,那么这三行代码没有什么区别

由此,能够得出一个结论,定义属性时候,atomic关键字为默认关键字。 你们都知道,atomic关键字修饰属性的性能要比nonatomic关键字修饰属性的性能要低。因此一般在iOS开发中,定义属性使用nonatomic。目的就是为了提升性能,节省可怜的资源。然而为何atomic关键字修饰的属性性能会低呢?面试

当定义一个属性以后,编译器会为自动为咱们生成带_(下划线)的成员变量以及getter/setter方法, 若是使用atomic修饰属性,那么在编译器为咱们生成setter/getter方法的时候,会作加锁的操做,加锁的目的就是为了保证存取值的安全性/完整性安全

场景: 若是使用atomic修饰属性值,有A和B两个线程,A线程对属性进行赋值,当A线程赋值进行一半的时候,因为加锁的缘故,A线程会持有这把锁,当B线程进行取值操做时候,发现A线程持有锁,那么会进行等待,当A线程赋值操做结束后,会放开锁,那么B线程持有这把锁,因此能够保证B线程必定能够取到一个完整的值。bash

若是使用nonatomic修饰属性值,有A和B两个线程,A线程对属性进行赋值,当A线程赋值进行一半的时候,B线程进行取值操做,因为没有加锁,B线程取不到一个完整的值,拿到一个不完整的值去作一些操做就可能会发生意想不到的事情。性能

atomic并不能保证线程是安全的atom

场景: 使用atomic修饰属性,若是有A、B和C三个线程。其中A和B线程同时对一个属性进行赋值操做,当赋值一半的时候,C线程进行取值操做,那么能够保证C线程必定能够取到一个完整的值,可是这个值的内容多是A线程赋的值,也多是B线程赋的值,也多是原始值,虽然取得了完整的值,可是这个值不必定是程序员想要的,因此说atomic并非线程安全的。spa

为何说atomic关键字是消耗性能的?线程

由于,atomic底层有加锁的操做,不管是什么锁,内存都会有必定的开销,性能确定会比nonatomic低。code

在平时开发的时候,不涉及线程安全的时候,好比一些UI控件必须在主线程操做的,用nonatomic能够提升性能。而真正要涉及线程安全,不能只靠编译器,须要程序员本身控制。内存

相关文章
相关标签/搜索