iOS 進階 - 記憶體管理(三) -- 資料結構
阿新 • • 發佈:2021-01-10
思維導圖
概述
- 記憶體佈局(iOS 系統下的記憶體佈局是什麼樣的?)
- 記憶體管理方案(iOS作業系統是怎麼對記憶體進行管理的?)
- 資料結構(更好的講述記憶體管理方案相關的問題,就要明白他們的資料結構)
- ARC&MRC(什麼是ARC,什麼是MRC,他們的區別以及各自實現的機制、原理)
- 引用計數機制(什麼是引用計數機制?記憶體是怎樣管理的?)
- 弱引用表(我們宣告weak的一個變數,為什麼在記憶體釋放的時候,weak指標會自動置為nil?弱引用變數記憶體是怎麼管理的?)
- 自動釋放池(AutoReleasePool)的實現機制和原理是怎樣的?
- 迴圈引用(常考點和易錯點,考察對記憶體管理理解的深度)
資料結構(散列表)
有關散列表實現的記憶體管理方案涉及到的一些資料結構
自旋鎖Spinlock_t
你是否使用過自旋鎖,自旋鎖和普通鎖有什麼區別,自旋鎖有哪些使用場景呢?
- 是一種"忙等"的鎖,如果當前鎖已被其他執行緒獲取,當前執行緒會不斷探測這個鎖有沒有被釋放,如果被釋放了,執行緒就會第一時間去獲取這個鎖。
- 比如說其他的鎖,比如訊號量,當它獲取不到這個鎖時,會把自己的執行緒進行阻塞休眠,然後等到其他執行緒釋放這個鎖的時候,再喚醒當前執行緒
- 自旋鎖適用於輕量訪問。(比如說上面Side Table表,如果說我們對某一個物件來進行引用計數操作的話,來訪問這個表,
實際上做+1-1操作是非常快的操作,那麼我們可以把它定義為輕量訪問。我們在這種輕量訪問的場景下,可以使用自旋鎖。)
引用計數表RefcountMap
- 引用計數表是雜湊表,可以理解為是一個字典,可以通過指標,找到對應物件的引用計數,這個查詢過程是一個雜湊查詢。
- 這個雜湊演算法實際上是對傳入物件的指標做一個偽裝的操作,然後去獲取對應的引用計數(size_t)
- 之所以使用雜湊查詢,是為了提高查詢效率。
- size_t表達的就是物件的引用計數值,是一個無符號long型的變數
查詢效率的提高,是因為我們儲存一個物件的引用計數時,是通過同一個函式來計算儲存位置的,而獲取物件的引用計數值的時候,也通過同一個函式來計算應該獲取的索引位置,因為插入和獲取都是通過同一個函式來計算位置,就會避免迴圈遍歷的操作。所以才說,雜湊查詢可以提高查詢效率。
size_t每一個bit為代表的含義
假如引用計數儲存是用64位來表示的
- 第1個二進位制位(weakly_referenced)表示物件是否有弱引用
- 第2位(deallocating)表示當前物件是否正在delloc
- 其他(RC)儲存這個物件的實際引用計數值
- 當我們計算物件的引用計數時,需要對這個值進行向右偏移兩位,因為要去掉後面兩位,才可以取到真實的引用計數值
弱引用表weak_table_t
- 在Runtime原始碼中可以看到,弱引用表示根據weak_table_t來定義的,weak_table_t也是一張雜湊表,給與一個物件的指標作為key,通過一個雜湊函式,就可以計算出對應的弱引用的物件的儲存位置。
- weak_entry_t實際上也是一個結構體陣列,這個陣列中儲存的每一個物件就是實際的弱引用指標,也就是我們在程式碼當中定義的類似於__weak id obj,那麼這個obj記憶體地址或者說這個指標就儲存在weak_entry_t這個結構體陣列中。