一般當(dāng)我們想要保證對(duì)象屬性的線程安全的時(shí)候可以在定義屬性的時(shí)候用 atomic 關(guān)鍵字來修飾,那么
這篇文章讓我們來探討一下atomic和nonatomic分別都替我們做了什么工作
兩個(gè)關(guān)鍵字修飾的OC對(duì)象 系統(tǒng)都會(huì)自動(dòng)生成setter/getter方法势木,區(qū)別就在于一個(gè)會(huì)進(jìn)行加鎖操作,一個(gè)不會(huì)耻煤。系統(tǒng)默認(rèn)是使用atomic的。
因?yàn)閍tomic做了線程鎖,所以理論上講atomic是要比nonatomic更加耗費(fèi)性能哈蝇、更慢棺妓。
atomic 系統(tǒng)會(huì)在生成的setter/getter方法里添加鎖,但是這個(gè)鎖僅僅是保證了setter/getter存取的安全炮赦,并不能保證數(shù)據(jù)結(jié)果正確怜跑,舉個(gè)??
A線程執(zhí)行setter方法到一半的時(shí)候,B線程執(zhí)行g(shù)etter方法吠勘,那么B線程的getter方法會(huì)被阻塞性芬,等到setter繼續(xù)執(zhí)行完成之后才能取到值。這里系統(tǒng)使用的也是 @synchronized 可以參考這里
A剧防、B植锉、C等多個(gè)線程都要操作同一個(gè)對(duì)象setter,D線程要getter這個(gè)對(duì)象的值峭拘,那么每個(gè)線程都成保證各自數(shù)據(jù)的完整性俊庇,但是D線程最后get到的值并不能確定。
以上鸡挠,所以atomic能夠保證數(shù)據(jù)的完成性辉饱,也就是說他只是讀寫安全,并不能準(zhǔn)確定義說他是線程安全的拣展。因?yàn)榫€程可以對(duì)數(shù)據(jù)做很多操作彭沼,包括讀寫,還有release瞎惫、retain,假如說對(duì)一個(gè)已經(jīng)釋放的對(duì)象進(jìn)行release溜腐,就會(huì)導(dǎo)致crash
by the way
@synthesize和@dynamic的區(qū)別
@synthesize var= _var是默認(rèn)的译株,如果你沒有手動(dòng)實(shí)現(xiàn)setter/getter方法瓜喇,那么編譯器就會(huì)自動(dòng)給你加上這兩個(gè)方法
atomic關(guān)鍵字實(shí)現(xiàn)setter/getter方法如下
@synthesize username = _username;
- (void)setUsername:(NSString *)username {
@synchronized(self) {
if (_username != username) {
_username = username;
}
}
}
- (NSString *)username {
NSString * str = nil;
@synchronized(self) {
str = _username;
}
return str;
}
@dynamic 則是告訴編譯器,用戶自己去實(shí)現(xiàn)setter/getter方法歉糜,但是如果你這么申明了乘寒,最后卻沒有手動(dòng)去實(shí)現(xiàn),那么編譯可能是沒問題的匪补,可是到程序執(zhí)行到obj.var = svar的時(shí)候伞辛,會(huì)因?yàn)檎也坏椒椒ǘ鴆rash.