iOS開發中使用@property聲明屬性時,常常用到atomic與nonatomic兩個關鍵字git
@property(nonatomic,strong)UIImage *icon; @property(strong)UIImage *icon1;//不寫默認atomic 複製代碼
atomic與nonatomicd的主要區別就是系統自動生成的getter/setter方法不同github
系統生成的getter/setter方法會進行加鎖操做,注意:這個鎖僅僅保證了getter和setter存取方法的線程安全.編程
由於getter/setter方法有加鎖的緣故,故在別的線程來讀寫這個屬性以前,會先執行完當前操做.安全
例如: 線程1調用了某一屬性的setter方法並進行到了一半,線程2調用其getter方法,那麼會執行完setter操做後,在執行getter操做,線程2會獲取到線程1 setter後的完整的值.markdown
當幾個線程同時調用同一屬性的setter、getter方法時,會get到一個完整的值,但get到的值不可控.多線程
例如: 線程1 調用getter 線程2 調用setter 線程3 調用setter 這3個線程並行同時開始,線程1會get到一個值,可是這個值不可控,多是線程2,線程3 set以前的原始值,多是線程2 set的值,也多是線程3 set的值oop
不是, 不少文章談到atomic和nonatomic的區別時,都說atomic是線程安全,其實這個說法是不許確的. atomic只是對屬性的getter/setter方法進行了加鎖操做,這種安全僅僅是set/get 的讀寫安全,並不是真正意義上的線程安全,由於線程安全還有讀寫以外的其餘操做(好比:若是當一個線程正在get或set時,又有另外一個線程同時在進行release操做,可能會直接crash)atom
系統生成的getter/setter方法沒有加鎖 線程不安全,但更快 當多個線程同時訪問同一個屬性,會出現沒法預料的結果spa
下面咱們新建一個nonatomic和一個atomic變量,並用代碼演示其內部實現線程
//interface @property(nonatomic,strong)UIImage *icon;//nonatomic @property(strong)UIImage *icon1;//atomic 複製代碼
nonatomic對象setter和getter方法的實現
//mrc 環境 //implementation @synthesize icon = _icon; //set -(void)setIcon:(UIImage *)icon { if(_icon != icon) { [_icon release]; _icon = [icon retain]; } } //get -(UIImage *)icon { return _icon; } 複製代碼
atomic對象setter和getter方法的實現
//mrc 環境 //implementation @synthesize icon1 = _icon1; //set -(void)setIcon1:(UIImage *)icon1 { //同步代碼塊 @synchronized (self) { if(_icon1 != icon1) { [_icon1 release]; _icon1 = [icon1 retain]; } } } //get -(UIImage *)icon1 { UIImage *image = nil; //同步代碼塊 @synchronized (self) { image = [[_icon1 retain] autorelease]; } return image; } 複製代碼
atomic只是保證了getter和setter存取方法的線程安全,並不能保證整個對象是線程安全的,所以在多線程編程時,線程安全還須要開發者本身來處理.
關於選擇:atomic系統生成的getter、setter會保證get、set操做的安全性,但相對nonatomic來講,atomic要更耗費資源,且速度要慢,故在iPhone等小型設備上,若是沒有多線程之間的通信,使用nonatomic是更好的選擇