前言
iOS開發中使用@property宣告屬性時,經常用到atomic與nonatomic兩個關鍵字
@property(nonatomic,strong)UIImage *icon;
@property(strong)UIImage *icon1;//不寫預設atomic
複製程式碼
atomic與nonatomicd的主要區別就是系統自動生成的getter/setter方法不一樣
- atomic系統自動生成的getter/setter方法會進行加鎖操作
- nonatomic系統自動生成的getter/setter方法不會進行加鎖操作
atomic
系統生成的getter/setter方法會進行加鎖操作,注意:這個鎖僅僅保證了getter和setter存取方法的執行緒安全.
因為getter/setter方法有加鎖的緣故,故在別的執行緒來讀寫這個屬性之前,會先執行完當前操作.
例如:
執行緒1呼叫了某一屬性的setter方法並進行到了一半,執行緒2呼叫其getter方法,那麼會執行完setter操作後,在執行getter操作,執行緒2會獲取到執行緒1 setter後的完整的值.
當幾個執行緒同時呼叫同一屬性的setter、getter方法時,會get到一個完整的值,但get到的值不可控.
例如:
執行緒1 呼叫getter
執行緒2 呼叫setter
執行緒3 呼叫setter
這3個執行緒並行同時開始,執行緒1會get到一個值,但是這個值不可控,可能是執行緒2,執行緒3 set之前的原始值,可能是執行緒2 set的值,也可能是執行緒3 set的值
atomic是執行緒安全的嗎?
不是,
很多文章談到atomic和nonatomic的區別時,都說atomic是執行緒安全,其實這個說法是不準確的.
atomic只是對屬性的getter/setter方法進行了加鎖操作,這種安全僅僅是set/get 的讀寫安全,並非真正意義上的執行緒安全,因為執行緒安全還有讀寫之外的其他操作(比如:如果當一個執行緒正在get或set時,又有另一個執行緒同時在進行release操作,可能會直接crash)
nonatomic
系統生成的getter/setter方法沒有加鎖
執行緒不安全,但更快
當多個執行緒同時訪問同一個屬性,會出現無法預料的結果
內部實現
下面我們新建一個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是更好的選擇
程式碼地址:github.com/CoderZhuXH/…