iOS基礎(chǔ)知識總結(jié)--atomic為什么不是線程安全

概述:

1、原子操作對線程安全并無任何安全保證。被atomic修飾的屬性(不重載設(shè)置器和訪問器)只保證了對數(shù)據(jù)讀寫的完整性赠潦,也就是原子性是辕,但是與對象的線程安全無關(guān)薄辅。

2静浴、線程安全已經(jīng)有保障情況下勿她、對性能也有要求的情況下可使用nonatomic替代atomic即横,當(dāng)然也可以一直使用atomic噪生。

描述:

首先我要糾正一個網(wǎng)上常見的關(guān)于atomic非線程安全的舉例:如果線程 A 調(diào)了 getter,與此同時線程 B 东囚、線程 C 都調(diào)了 setter——那最后線程 A get 到的值跺嗽,有3種可能:可能是 B、C set 之前原始的值页藻,也可能是 B set 的值桨嫁,也可能是 C set 的值。同時份帐,最終這個屬性的值璃吧,可能是 B set 的值,也有可能是 C set 的值废境。所以atomic可并不能保證對象的線程安全畜挨。

類似的這個例子相信很多人都見過,看起來也非常合理噩凹,沒什么錯朦促;但細(xì)琢磨,這個例子本身沒問題栓始,但根本不能證明atomic的非線程安全這個觀點(diǎn)!所以面試的時候如果舉這個例子Q薄(說明你就沒明白atomic的非線程安全性)

首先你得知道什么是線程不安全幻赚,線程的不安全是由于多線程訪問和修改共享資源而引起的不可預(yù)測的結(jié)果(有可能crash)禀忆。可以簡單理解為我們拿到的值是錯的落恼。這個例子中箩退,如果線程A getter到的值是個錯誤的值才能說是線程不安全的,可是這個例子就算線程A可能取到好幾種值佳谦,你能說取值不對嗎戴涝;不能。所以這個例子是個錯誤的例子钻蔑!

atomic的原子性和nonatomic的非原子性

atomic :系統(tǒng)自動生成的getter/setter方法會進(jìn)行加鎖操作啥刻;可以理解過讀寫鎖,可以保證讀寫安全咪笑;較耗時可帽;

nonatomic : 系統(tǒng)自動生成的getter/setter方法不會進(jìn)行加鎖操作;但速度會更快窗怒;

下面是兩個nonatomic和atomic修飾的變量映跟,我們用代碼掩飾其內(nèi)部實(shí)現(xiàn);


nonatomic和atomic修飾的變量代碼實(shí)現(xiàn)

atomic的原子性和nonatomic的非原子性官方解釋

原子的(默認(rèn))

--原子是默認(rèn)設(shè)置:如果您不輸入任何內(nèi)容扬虚,則您的屬性是原子的努隙。

--原子屬性可以保證,如果您嘗試從中讀取內(nèi)容辜昵,則將取回有效值荸镊。

--它不能保證該值是多少,但是您將獲得合法有效的數(shù)據(jù)路鹰,而不僅僅是垃圾內(nèi)存(又叫臟數(shù)據(jù))贷洲。

--這允許您執(zhí)行的操作是,如果您有多個線程或多個進(jìn)程指向一個變量晋柱,則一個線程可以讀取而另一個線程可以寫入优构。

--如果它們同時命中,則保證讀取器線程獲得兩個值之一:更改之前或更改之后雁竞。

--原子不會給您帶來任何保證钦椭,您可能會獲得其中哪些值。

--原子通常確實(shí)與線程安全混淆碑诉,這是不正確的彪腔。

--您需要以其他方式保證線程安全。但是进栽,atomic可以保證德挣,如果您嘗試讀取數(shù)據(jù),則肯定會獲得某種合法數(shù)據(jù)快毛。

非原子

--另一方面格嗅,您可能會猜到番挺,非原子意味著“不要做原子的事情”。

--您所失去的是保證您總是能得到一些回報屯掖。

--如果嘗試在寫入過程中進(jìn)行讀取玄柏,則可能會獲取垃圾數(shù)據(jù)。

--但是贴铜,另一方面粪摘,您走得更快。

--因?yàn)樵訉傩员仨氉鲆恍┠g(shù)(遞歸鎖)才能保證您將獲得一個值绍坝,所以它們要慢一些徘意。

--如果這是您經(jīng)常訪問的屬性,則可能需要降低為非原子屬性陷嘴,以確保不會造成速度損失映砖。

分析atomic為什么不是線程安全

其實(shí)現(xiàn)在一想很奇怪,為什么要把a(bǔ)tomic和線程安全聯(lián)系在一起去探究灾挨;atomic只是對屬性的getter/setter方法進(jìn)行了加鎖操作邑退,這種安全僅僅是get/set的讀寫安全,僅此之一劳澄,但是線程安全還有除了讀寫的其他操作,比如:當(dāng)一個線程正在get/set時地技,另一個線程同時進(jìn)行release操作,可能會直接crash秒拔。很明顯atomic的讀寫鎖不能保證線程安全莫矗。 下面兩個例子寫的就挺好,挺簡單:

eg1:如果定義屬性NSInteger i是原子的砂缩,對i進(jìn)行i = i + 1操作就是不安全的作谚; 因?yàn)樵有灾荒鼙WC讀寫安全,而該表達(dá)式需要三步操作:

1庵芭、讀取i的值存入寄存器妹懒;

2、將i加1双吆;

3眨唬、修改i的值;

如果在第一步完成的時候好乐,i被其他線程修改了匾竿,那么表達(dá)式執(zhí)行的結(jié)果就與預(yù)期的不一樣,也就是不安全的

?eg2:


結(jié)果可能是[10000,20000]之間的某個值蔚万,而我們想要的結(jié)果是20000岭妖;很明顯這個例子就會引起線程隱患,而atomic并不能防止這個問題;所以我們說atomic不是線程安全昵慌;


擴(kuò)展:探索nonatomic非線程安全的原因

為什么nonatomic是非線程安全的苔巨,我們來看看runtime的源碼:


runtime-get


runtime-set

根據(jù)源碼,我們可以看到废离,getter是不會對屬性進(jìn)行retain的,假設(shè)當(dāng)getter執(zhí)行后礁芦,切換到另一個線程蜻韭,執(zhí)行setter,setter會對oldValue release柿扣,導(dǎo)致oldValue釋放肖方。再切回執(zhí)行g(shù)etter的線程,getter用到的是已經(jīng)釋放的oldValue未状。就會發(fā)生EXC_BAD_ACCESS的crash俯画。

一般情況下,getter執(zhí)行后司草,會在外部對getter獲取的屬性進(jìn)行retain艰垂,也就是調(diào)用objc_retain。但是也許就在getter發(fā)生之后埋虹,objc_retain之前其他線程執(zhí)行了setter猜憎。這時候,就會導(dǎo)致objc_retain產(chǎn)生EXC_BAD_ACCESS搔课。

那么atomic會不會發(fā)生問題呢胰柑?根據(jù)源碼,在獲取到屬性時爬泥,atomic下getter會立即對value進(jìn)行retain柬讨,即使setter對oldValue release了。由于getter已經(jīng)進(jìn)行retain袍啡,屬性不會立即釋放踩官。只有使用完成之后才會釋放。所以atomic在操作屬性的時候可以保證不會crash葬馋。


再次來個總結(jié):

nonatomic在線程間切換操作屬性的時候容易造成crash卖鲤,是不安全的。

atomic在線程間切換操作屬性可以保證不會crash畴嘶,也會get到合法的有效數(shù)據(jù)蛋逾,但是并不能保證獲取的數(shù)據(jù)就是你的預(yù)期值。也是不安全的窗悯。


借鑒文章:

談nonatomic非線程安全問題

從源代碼理解atomic為什么不是線程安全

atomic 與 nonatomic 與 線程安全到底什么關(guān)系区匣?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亏钩,更是在濱河造成了極大的恐慌莲绰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姑丑,死亡現(xiàn)場離奇詭異蛤签,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)栅哀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門震肮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人留拾,你說我怎么就攤上這事戳晌。” “怎么了痴柔?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵沦偎,是天一觀的道長。 經(jīng)常有香客問我咳蔚,道長豪嚎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任屹篓,我火速辦了婚禮疙渣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堆巧。我一直安慰自己妄荔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布谍肤。 她就那樣靜靜地躺著啦租,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荒揣。 梳的紋絲不亂的頭發(fā)上篷角,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音系任,去河邊找鬼恳蹲。 笑死,一個胖子當(dāng)著我的面吹牛俩滥,可吹牛的內(nèi)容都是我干的嘉蕾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼霜旧,長吁一口氣:“原來是場噩夢啊……” “哼错忱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤以清,失蹤者是張志新(化名)和其女友劉穎儿普,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掷倔,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眉孩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了勒葱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勺像。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖错森,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情篮洁,我是刑警寧澤涩维,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站袁波,受9級特大地震影響瓦阐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篷牌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一睡蟋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枷颊,春花似錦戳杀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至题造,卻和暖如春傍菇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背界赔。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工丢习, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淮悼。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓咐低,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敛惊。 傳聞我的和親對象是個殘疾皇子渊鞋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容