iOS中atomic和nonatomic區別及內部實現

朱曉輝Allen發表於2019-03-04
iOS中atomic和nonatomic區別及內部實現

前言

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/…

相關文章