前言
atomic/nonatomic 是屬性修飾符之一摔笤,atomic 代表原子性,nonatomic 代表非原子性垦写;
原子性是防止方法調(diào)用到一半其它操作再次進(jìn)入該方法吕世,導(dǎo)致出現(xiàn)異常情況。
atomic 和 nonatomic 區(qū)別以及實(shí)現(xiàn)
首先我們知道 atomic 代表原子性梯投,nonatomic 代表非原子性命辖;用這兩個(gè)修飾符來(lái)修飾屬性,區(qū)別主要在于屬性的 getter/setter 方法:atomic 會(huì)對(duì) setter 方法進(jìn)行加鎖分蓖,nonatomic 不會(huì)對(duì) setter 方法加鎖尔艇。
atomic 修飾的屬性,在 setter 方法中使用@synchronized加鎖來(lái)確保原子操作么鹤,但是@synchronized相比于其它類型的鎖终娃,性能是最低效的,因?yàn)槌思渔i之外蒸甜,額外還會(huì)設(shè)置異常處理機(jī)制棠耕,性能消耗較大。這里就是為什么平時(shí)開發(fā)中很少使用 atomic 來(lái)修飾屬性迅皇。
atomic 與 nonatomic 在 getter/setter 方法區(qū)別如下:
atomic 不保證線程安全
atomic 只會(huì)保證 setter/getter 方法是原子操作的昧辽,防止方法調(diào)用到一半其它操作再次進(jìn)入該方法,導(dǎo)致出現(xiàn)異常情況登颓。即原子性保證你訪問(wèn)的時(shí)候給你返回一個(gè)完好無(wú)損的對(duì)象搅荞,但是不會(huì)保證線程安全,這里有個(gè)經(jīng)典的例子:
如果線程 A 調(diào)了 getter框咙,與此同時(shí)線程 B 咕痛、線程 C 都調(diào)了 setter——那最后線程 A get 到的值,有3種可能:可能是 B喇嘱、C set之前原始的值茉贡,也可能是 B set的值,也可能是 C set的值者铜。同時(shí)腔丧,最終這個(gè)屬性的值放椰,可能是 B set的值,也有可能是 C set的值愉粤。所以atomic可并不能保證對(duì)象的線程安全砾医。
這個(gè)問(wèn)題其實(shí)包括兩個(gè)塊內(nèi)存,一個(gè)是棧區(qū)指針的內(nèi)存A衣厘,一個(gè)是堆區(qū)對(duì)象占用的內(nèi)存B如蚜。
atomic 只是對(duì)屬性的 getter/setter 方法加自旋鎖,也就是對(duì)A加鎖影暴,這樣可以保證A是線程安全的错邦。這樣并沒(méi)有對(duì)B做任何處理,所以B不是線程安全的型宙。
如果一個(gè)對(duì)象的改變不是直接調(diào)用 getter/setter 方法撬呢,而是直接對(duì)對(duì)象內(nèi)部屬性修改、字符串拼接妆兑、數(shù)組增加和移除元素等操作倾芝,就不能保證這個(gè)對(duì)象是線程安全的。