一、atomic與nonatomic的區(qū)別文留!
首先题禀,先介紹一下atomic
和nonatomic
1.atomic
使用同步鎖,原子性:
在該屬性在調(diào)用getter
和setter
方法時(shí)穴店,會(huì)加上自旋鎖(osspinlock)
撕捍,
即在屬性在調(diào)用getter
和setter
方法時(shí),保證同一時(shí)刻只能有一個(gè)線程調(diào)用屬性的讀/寫方
2.nonatomic
:不使用同步鎖泣洞,非原子性:
在該屬性在調(diào)用getter和setter方法時(shí)忧风,不會(huì)加上自旋鎖
,也就是線程并不安全
然后球凰,再介紹一下atomic
和nonatomic
的申明方式
@property(nonatomic,strong) NSString *test;
@property (atomic,strong) NSString *test;
@property (strong) NSString *test;
代碼中可以看到這樣的書寫方式狮腿,那么這三個(gè)代碼有什么不同呢?
其實(shí):
@property (atomic,strong) NSString *test;
@property (strong) NSString *test;
這兩個(gè)代碼完全是一樣的結(jié)果,省略不寫即默認(rèn)為atomic
呕诉,而不是nonatomic
中間缘厢,我為什么強(qiáng)調(diào)atomic
屬性申明時(shí)在調(diào)用getter
和setter
方法時(shí)會(huì)加上自旋鎖(osspinlock)
并且是只能有一個(gè)線程調(diào)用屬性的讀/寫方法,沒有說線程是安全的
對(duì)于atomic
的屬性甩挫,系統(tǒng)生成的 getter/setter
會(huì)保證 get贴硫、set
操作的完整性,不受其他線程影響捶闸。
比如夜畴,線程 A 的 getter
方法運(yùn)行到一半,線程 B 調(diào)用了 setter:
那么線程 A 的 getter
還是能得到一個(gè)完好無損的對(duì)象删壮。
如果有一個(gè) atomic
的屬性 "name"
贪绘,如果線程 A 調(diào)[self setName:@"A"]
,線程 B 調(diào)[self setName:@"B"]
央碟,線程 C 調(diào)[self name]
税灌,那么所有這些不同線程上的操作都將依次順序執(zhí)行——也就是說均函,如果一個(gè)線程正在執(zhí)行 getter/setter
,其他線程就得等待菱涤。因此苞也,屬性 name
是讀/寫安全的。
但是粘秆,如果有另一個(gè)線程 D 同時(shí)在調(diào)[name release]
如迟,那可能就會(huì)crash
,因?yàn)?release
不受 getter/setter
操作的限制攻走。也就是說殷勘,這個(gè)屬性只能說是讀/寫
安全的,但并不是線程安全
的昔搂,因?yàn)閯e的線程還能進(jìn)行讀寫
之外的其他操作玲销。線程安全
需要開發(fā)者自己來保證
最后為什么說nonatomic
線程并不安全
如果 name
屬性是 nonatomic
的,那么上面例子里的所有線程 A摘符、B贤斜、C、D 都可以同時(shí)執(zhí)行逛裤,可能導(dǎo)致無法預(yù)料的結(jié)果瘩绒。如果是atomic
的,那么 A带族、B草讶、C 會(huì)串行,而 D 還是并行的炉菲。
其實(shí)蘋果官方文檔也有解釋
還有自旋鎖osspinlock
因?yàn)椴⒉话踩呀?jīng)被蘋果淘汰,替換成為自旋鎖os_unfair_lock
,詳情可以參考YY大神ibireme
不再安全的 OSSpinLock