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

前言

iOS開發中使用@property聲明屬性時,常常用到atomic與nonatomic兩個關鍵字git

@property(nonatomic,strong)UIImage *icon;
@property(strong)UIImage *icon1;//不寫默認atomic
複製代碼

atomic與nonatomicd的主要區別就是系統自動生成的getter/setter方法不同github

  • atomic系統自動生成的getter/setter方法會進行加鎖操做
  • nonatomic系統自動生成的getter/setter方法不會進行加鎖操做

atomic

系統生成的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是線程安全的嗎?

不是, 不少文章談到atomic和nonatomic的區別時,都說atomic是線程安全,其實這個說法是不許確的. atomic只是對屬性的getter/setter方法進行了加鎖操做,這種安全僅僅是set/get 的讀寫安全,並不是真正意義上的線程安全,由於線程安全還有讀寫以外的其餘操做(好比:若是當一個線程正在get或set時,又有另外一個線程同時在進行release操做,可能會直接crash)atom

nonatomic

系統生成的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是更好的選擇

代碼地址:github.com/CoderZhuXH/…

相關文章
相關標籤/搜索