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能夠提升性能。而真正要涉及線程安全,不能只靠編譯器,須要程序員本身控制。內存

相關文章
相關標籤/搜索