ios runloop的Autorelease對(duì)象釋放的背后

前言:

Autorelease機(jī)制對(duì)于iOS開(kāi)發(fā)人員對(duì)對(duì)象的內(nèi)存管理省下不少心血,說(shuō)白了就是你甭管內(nèi)存的管理問(wèn)題次绘,我會(huì)在背后幫你處理,不需要你操碎了心去避雷,這就是ARC的最大的好處未妹!正所謂任何事情都是一把雙刃劍,還有一個(gè)block里面循環(huán)引用的雷池要注意的空入,如何注意其實(shí)很簡(jiǎn)單络它,在這就不說(shuō)了。

runloop:

runloop是什么的東西歪赢,runloop就好比一個(gè)特務(wù)化戳,接到任務(wù)就去處理,沒(méi)任務(wù)就休假埋凯,等待任務(wù)点楼,任務(wù)有很多類型的。相對(duì)于線程白对,做完一個(gè)任務(wù)就掛掉了掠廓,runloop還是有很大的優(yōu)勢(shì)的,先看看runloop的大概流程圖:


圖1

上圖的2-9流程就是這個(gè)”特務(wù)“的處理任務(wù)甩恼,休假蟀瞧,接到任務(wù)作處理,處理完后再休假(等待任務(wù))的一個(gè)循環(huán)悦污,我說(shuō)了這么多,跟標(biāo)題的內(nèi)容有什么關(guān)系呢屈溉?關(guān)系是有的塞关,本篇重點(diǎn)就在第6點(diǎn)里面了。

圖中第1條的 Observer 監(jiān)視的事件是 Entry(即將進(jìn)入Loop)子巾,其回調(diào)內(nèi)會(huì)調(diào)用 _objc_autoreleasePoolPush() 創(chuàng)建自動(dòng)釋放池帆赢。其 order 是-2147483647,優(yōu)先級(jí)最高线梗,保證創(chuàng)建釋放池發(fā)生在其他所有回調(diào)之前椰于。

這個(gè)用我的話稱為“外圍釋放池”的創(chuàng)建!

圖中第6 Observer 監(jiān)視了兩個(gè)事件: BeforeWaiting(準(zhǔn)備進(jìn)入休眠) 時(shí)調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池仪搔;Exit(即將退出Loop) 時(shí)調(diào)用 _objc_autoreleasePoolPop() 來(lái)釋放自動(dòng)釋放池瘾婿。這個(gè) Observer 的 order 是 2147483647,優(yōu)先級(jí)最低,保證其釋放池子發(fā)生在其他所有回調(diào)之后偏陪。

圖中第10 Observer 監(jiān)視事件是exit(即講退出runloop)抢呆,其回調(diào)內(nèi)會(huì)調(diào)用 _objc_autoreleasePoolpop() 釋放自動(dòng)釋放池。

這個(gè)用我的話稱為“外圍析放池”的釋放笛谦!

那么第6步的優(yōu)先級(jí)低的釋放池?zé)o論被創(chuàng)建和釋放多少次也對(duì)“外圍釋放池”沒(méi)影響了抱虐,也符合了這個(gè)邏輯思維了!

好了饥脑,上面的內(nèi)容是對(duì)標(biāo)題的內(nèi)容作一個(gè)鋪墊恳邀,那么我今天要深入說(shuō)的就是第6步監(jiān)聽(tīng)的回調(diào)的實(shí)現(xiàn)原理,也就是Autorelease的原理

各位灶轰,先想想這個(gè)“Autorelease對(duì)象什么時(shí)候被切底釋放谣沸?”

答:當(dāng)前作用域大括號(hào)結(jié)束時(shí)釋放。答案真的是這樣嗎笋颤?也許手動(dòng)添加Autorelease pool是這樣的乳附!

真正的答案是:在非手動(dòng)添加Autorelease pool下,Autorelease對(duì)象是在當(dāng)前runloop進(jìn)入休眠等待前被釋放的椰弊,為何會(huì)這樣许溅,接下來(lái)一一探究瓤鼻。

Autorelease內(nèi)部原理

Autoreleasepool{} 編譯后是這樣的:

void * context = objc_autoreleasePoolPush();

{}// 內(nèi)部要做的事情

objc_autoreleasePoolPush(context);

這兩個(gè)方法是對(duì)AutoreleasePoolPage的一個(gè)簡(jiǎn)單封裝秉版,其核心就在這個(gè)類里面,AutoreleasePoolPage是一個(gè)C++實(shí)現(xiàn)的類茬祷;看看里面的內(nèi)容


圖2


1.AutoreleasePool并沒(méi)有單獨(dú)的結(jié)構(gòu)清焕,而是由若干個(gè)AutoreleasePoolPage以雙向鏈表的形式組合而成(分別對(duì)應(yīng)結(jié)構(gòu)中的parent指針和child指針)。

2.AutoreleasePool是按線程一一對(duì)應(yīng)的(結(jié)構(gòu)中的thread指針指向當(dāng)前線程)祭犯。

3.AutoreleasePoolPage每個(gè)對(duì)象會(huì)開(kāi)辟4096字節(jié)內(nèi)存(也就是虛擬內(nèi)存一頁(yè)的大薪胀住),除了上面的實(shí)例變量所占空間沃粗,剩下的空間全部用來(lái)儲(chǔ)存autorelease對(duì)象的地址粥惧。

4.上面的id *next指針作為游標(biāo)指向棧頂最新注冊(cè)進(jìn)來(lái)的autorelease對(duì)象的下一個(gè)位置。

5.一個(gè)AutoreleasePoolPage的空間被占滿時(shí)最盅,會(huì)新建一個(gè)AutoreleasePoolPage對(duì)象突雪,連接鏈表(用結(jié)構(gòu)中的parent指針和child指針?lè)謩e指向舊的AutoreleasePoolPage和新的AutoreleasePoolPage),后來(lái)的autorelease對(duì)象在新的page加入涡贱。

當(dāng)我們創(chuàng)建好注冊(cè)進(jìn)來(lái)的對(duì)象就變成這樣


圖3


當(dāng)next 指針在棧頂?shù)牡鸵欢葍?nèi)存時(shí)咏删,當(dāng)再注冊(cè)一個(gè)對(duì)象進(jìn)來(lái)時(shí),那么系統(tǒng)就會(huì)創(chuàng)建一個(gè)新的AutoreleasePoolPage來(lái)保存對(duì)象问词,新的parent指針指向舊的AutoreleasePoolPage督函,形成鏈表的結(jié)構(gòu)一樣,保證釋放和新建AutoreleasePool能有序進(jìn)行。每向一個(gè)對(duì)象發(fā)送 autorelease 消息辰狡,就是把對(duì)象加入到next 指針處锋叨,next 指針向高內(nèi)存偏移一個(gè)位置(位置大小取決于新添加進(jìn)來(lái)的對(duì)象內(nèi)存的大小) 這是自動(dòng)釋放對(duì)象add進(jìn)來(lái)的大概原理宛篇。

釋放原理

好了悲柱,自動(dòng)釋放對(duì)象加進(jìn)來(lái)的大概原理我們清楚了,那么反過(guò)來(lái)些己,對(duì)象釋放的原理也差不多了豌鸡。。段标。 慢著涯冠,釋放時(shí)究竟我要釋放到那個(gè)位置呢?憑借什么去標(biāo)記呢逼庞?

內(nèi)涵在于每當(dāng)objc_autoreleasePoolPush被執(zhí)行時(shí)蛇更,runtime會(huì)向當(dāng)前AutoreleasePoolPage加入一個(gè)標(biāo)記,稱為“哨兵指針”赛糟,(我很喜歡這個(gè)名字)這個(gè)哨兵指針內(nèi)容是nil派任,看圖:


圖4


AutoreleasePoolPop主要做一下事情:

1.AutoreleasePoolPop要傳入的參數(shù)就是這個(gè)哨兵指針,首先找到這個(gè)哨兵指針?biāo)诘膒age璧南。

2.在next指針和哨兵指針之間的對(duì)象都發(fā)送一次 release消息掌逛,并把next指針移動(dòng)上一次設(shè)立哨兵指針的位置,(由于page結(jié)構(gòu)類似于鏈表司倚,所有這一步可以靠parent指針跨越多個(gè)page的對(duì)象作處理)

以上就是Autorelease內(nèi)部的實(shí)現(xiàn)原理豆混。

我形象點(diǎn)說(shuō)就是page就是一個(gè)氣泵,next指針就是那個(gè)活動(dòng)的活塞动知,哨兵指針地址就是那個(gè)頂點(diǎn)皿伺,當(dāng)我釋放對(duì)象時(shí)就等于我往里面壓縮,把活動(dòng)的活塞推到頂點(diǎn)盒粮,里面的空氣就是add進(jìn)來(lái)的對(duì)象鸵鸥,經(jīng)過(guò)活動(dòng)的活塞的頂點(diǎn)(next指針)向活塞推到頂點(diǎn)(哨兵指針位置)靠近時(shí),空氣(對(duì)象被釋放)被排出丹皱,當(dāng)活動(dòng)的活塞(next指針)被退回到活塞頂點(diǎn)(哨兵指針位置)妒穴,兩者之間的空氣被排出去了(對(duì)象被釋放了)這時(shí)候就不在推了,這時(shí)候當(dāng)再有對(duì)象add進(jìn)來(lái)時(shí)就像有空氣吹進(jìn)來(lái)种呐,把活動(dòng)的活塞的頂點(diǎn)(next指針)和活塞推到頂點(diǎn)(哨兵指針位置)一點(diǎn)一點(diǎn)隔開(kāi)宰翅,一到AutoreleasePoolPop時(shí)又以“推活塞“的形式去釋放對(duì)象了。

好了爽室,總結(jié)上下問(wèn)所說(shuō)的內(nèi)容:當(dāng)一個(gè)runloop在不停的循環(huán)工作汁讼,那么runloop每一次循環(huán)必定會(huì)經(jīng)過(guò)BeforeWaiting(準(zhǔn)備進(jìn)入休眠):而去BeforeWaiting(準(zhǔn)備進(jìn)入休眠) 時(shí)調(diào)用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池淆攻,那么這兩個(gè)方法來(lái)銷毀要釋放的對(duì)象,所以我們根本不需要擔(dān)心Autorelease的內(nèi)存管理問(wèn)題嘿架,這就是ARC背后的“高人”瓶珊。


最后,文章一些內(nèi)容引用到一些大神級(jí)別的博客的內(nèi)容耸彪,如有侵權(quán)伞芹,請(qǐng)及時(shí)聯(lián)系。

由于水平有限蝉娜,僅供大家學(xué)習(xí) (大神請(qǐng)無(wú)視)如有錯(cuò)誤唱较,請(qǐng)指正!

最后的最后貼上一些更深入了解的博客地址:

黑幕背后的Autorelease - CocoaChina_讓移動(dòng)開(kāi)發(fā)更簡(jiǎn)單

深入理解RunLoop - CocoaChina_讓移動(dòng)開(kāi)發(fā)更簡(jiǎn)單

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末召川,一起剝皮案震驚了整個(gè)濱河市南缓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荧呐,老刑警劉巖汉形,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異倍阐,居然都是意外死亡概疆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門峰搪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)岔冀,“玉大人,你說(shuō)我怎么就攤上這事罢艾¢沟撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵咐蚯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我弄贿,道長(zhǎng)春锋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任差凹,我火速辦了婚禮期奔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘危尿。我一直安慰自己呐萌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布谊娇。 她就那樣靜靜地躺著肺孤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赠堵,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天小渊,我揣著相機(jī)與錄音,去河邊找鬼茫叭。 笑死酬屉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的揍愁。 我是一名探鬼主播呐萨,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼莽囤!你這毒婦竟也來(lái)了垛吗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤烁登,失蹤者是張志新(化名)和其女友劉穎怯屉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體饵沧,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锨络,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狼牺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羡儿。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖是钥,靈堂內(nèi)的尸體忽然破棺而出掠归,到底是詐尸還是另有隱情,我是刑警寧澤悄泥,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布虏冻,位于F島的核電站,受9級(jí)特大地震影響弹囚,放射性物質(zhì)發(fā)生泄漏厨相。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一鸥鹉、第九天 我趴在偏房一處隱蔽的房頂上張望蛮穿。 院中可真熱鬧,春花似錦毁渗、人聲如沸践磅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)府适。三九已至羔飞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間细溅,已是汗流浹背褥傍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喇聊,地道東北人恍风。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像誓篱,于是被迫代替她去往敵國(guó)和親朋贬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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