
前言
iOS開發(fā)中使用@property聲明屬性時(shí),經(jīng)常用到atomic與nonatomic兩個(gè)關(guān)鍵字
@property(nonatomic,strong)UIImage *icon;
@property(strong)UIImage *icon1;//不寫默認(rèn)atomic
atomic與nonatomicd的主要區(qū)別就是系統(tǒng)自動(dòng)生成的getter/setter方法不一樣
- atomic系統(tǒng)自動(dòng)生成的getter/setter方法會(huì)進(jìn)行加鎖操作
- nonatomic系統(tǒng)自動(dòng)生成的getter/setter方法不會(huì)進(jìn)行加鎖操作
atomic
系統(tǒng)生成的getter/setter方法會(huì)進(jìn)行加鎖操作,注意:這個(gè)鎖僅僅保證了getter和setter存取方法的線程安全.
因?yàn)間etter/setter方法有加鎖的緣故,故在別的線程來讀寫這個(gè)屬性之前,會(huì)先執(zhí)行完當(dāng)前操作.
例如:
線程1調(diào)用了某一屬性的setter方法并進(jìn)行到了一半,線程2調(diào)用其getter方法,那么會(huì)執(zhí)行完setter操作后,在執(zhí)行g(shù)etter操作,線程2會(huì)獲取到線程1 setter后的完整的值.
當(dāng)幾個(gè)線程同時(shí)調(diào)用同一屬性的setter、getter方法時(shí),會(huì)get到一個(gè)完整的值,但get到的值不可控.
例如:
線程1 調(diào)用getter
線程2 調(diào)用setter
線程3 調(diào)用setter
這3個(gè)線程并行同時(shí)開始,線程1會(huì)get到一個(gè)值,但是這個(gè)值不可控,可能是線程2,線程3 set之前的原始值,可能是線程2 set的值,也可能是線程3 set的值
atomic是線程安全的嗎?
不是,
很多文章談到atomic和nonatomic的區(qū)別時(shí),都說atomic是線程安全,其實(shí)這個(gè)說法是不準(zhǔn)確的.
atomic只是對(duì)屬性的getter/setter方法進(jìn)行了加鎖操作,這種安全僅僅是set/get 的讀寫安全,并非真正意義上的線程安全,因?yàn)榫€程安全還有讀寫之外的其他操作(比如:如果當(dāng)一個(gè)線程正在get或set時(shí),又有另一個(gè)線程同時(shí)在進(jìn)行release操作,可能會(huì)直接crash)
nonatomic
系統(tǒng)生成的getter/setter方法沒有加鎖
線程不安全,但更快
當(dāng)多個(gè)線程同時(shí)訪問同一個(gè)屬性,會(huì)出現(xiàn)無法預(yù)料的結(jié)果
內(nèi)部實(shí)現(xiàn)
下面我們新建一個(gè)nonatomic和一個(gè)atomic變量,并用代碼演示其內(nèi)部實(shí)現(xiàn)
//interface
@property(nonatomic,strong)UIImage *icon;//nonatomic
@property(strong)UIImage *icon1;//atomic
nonatomic對(duì)象setter和getter方法的實(shí)現(xiàn)
//mrc 環(huán)境
//implementation
@synthesize icon = _icon;
//set
-(void)setIcon:(UIImage *)icon
{
if(_icon != icon)
{
[_icon release];
_icon = [icon retain];
}
}
//get
-(UIImage *)icon
{
return _icon;
}
atomic對(duì)象setter和getter方法的實(shí)現(xiàn)
//mrc 環(huán)境
//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;
}
總結(jié)
atomic只是保證了getter和setter存取方法的線程安全,并不能保證整個(gè)對(duì)象是線程安全的,因此在多線程編程時(shí),線程安全還需要開發(fā)者自己來處理.
關(guān)于選擇:atomic系統(tǒng)生成的getter、setter會(huì)保證get、set操作的安全性,但相對(duì)nonatomic來說,atomic要更耗費(fèi)資源,且速度要慢,故在iPhone等小型設(shè)備上,如果沒有多線程之間的通訊,使用nonatomic是更好的選擇