Go語言七篇入門教程七GC垃圾回收三色標記
GC
GC
全稱Garbage Collection
目前主流的垃圾回收算法有兩類,分別是追蹤式垃圾回收算法(Tracing garbage collection)和引用計數法( Reference counting )。
而三色標記法是屬於追蹤式垃圾回收算法的一種。
追蹤式算法的核心思想是判斷一個對象是否可達,因為一旦這個對象不可達就可以立刻被 GC 回收瞭。
如何判斷一個對象是否可達
分為兩步:
- 第一步找出所有的全局變量和當前函數棧裡的變量,標記為可達。
- 第二步,從已經標記的數據開始,進一步標記它們可訪問的變量,周而復始,這一過程也叫傳遞閉包。
在go推出三色標記法之前,go所使用的gc算法叫Mark-And-Sweep
(標記清掃)
這個算法就是嚴格按照追蹤式算法的思路來實現的。
- 先設置一個標志位來記錄對象是否被使用,最開始所有的標記位都是 0。
- 如果發現對象是可達的就會置為
1
,一步步下去就會呈現一個類似樹狀的結果。 - 等標記的步驟完成後,會將沒有被標記的對象統一清理,再次把所有的標記位設置成 0, 以便下次進行清理。
這個算法最大的問題是 GC
執行期間需要把整個程序完全暫停,不能異步進行GC
操作。因為在不同階段標記清掃法的標志位 0 和 1 有不同的含義,那麼新增的對象無論標記為什麼都有可能意外刪除這個對象。對實時性要求高的系統來說,這種需要長時間掛起的標記清掃法是不可接受的。所以就需要一個算法來解決 GC 運行時程序長時間掛起的問題,那就三色標記法。
三色標記法
三色標記法是傳統 Mark-Sweep 的一個改進,它是一個並發的 GC 算法。on-the-fly
原理如下
整個進程空間裡申請每個對象占據的內存可以視為一個圖, 初始狀態下每個內存對象都是白色標記。
先stop the world
,將掃描任務作為多個並發的goroutine立即入隊給調度器,進而被CPU處理,第一輪先掃描所有可達的內存對象,標記為灰色放入隊列
第二輪可以恢復start the world,將第一步隊列中的對象引用的對象置為灰色加入隊列,一個對象引用的所有對象都置灰並加入隊列後,這個對象才能置為黑色並從隊列之中取出。循環往復,最後隊列為空時,整個圖剩下的白色內存空間即不可到達的對象,即沒有被引用的對象;
第三輪再次stop the world
,將第二輪過程中新增對象申請的內存進行標記(灰色),這裡使用瞭writebarrier
(寫屏障)去記錄這些內存的身份;
這個算法可以實現 on-the-fly
,也就是在程序執行的同時進行收集,並不需要暫停整個程序。
簡化步驟如下:
1、首先創建三個集合:白、灰、黑。
2、將所有對象放入白色集合中。
3、然後從根節點開始遍歷所有對象(註意這裡並不遞歸遍歷),把遍歷到的對象從白色集合放入灰色集合。
因為root set 指向瞭A、F,所以從根結點開始遍歷的是A、F
,所以是把A、F放到灰色集合中。
4、之後遍歷灰色集合,將灰色對象引用的對象從白色集合放入灰色集合,之後將此灰色對象放入黑色集合
我們可以發現這個A指向瞭B,C,D所以也就是把BCD放到灰色中,把A放到黑色中,而F沒有指任何的對象,所以直接放到黑色中。
5、重復 4 直到灰色中無任何對象
因為D指向瞭A所以D也放到瞭黑色中,而B和C能放到黑色集合中的道理和F一樣,已經沒有瞭可指向的對象瞭。
6、通過write-barrier
檢測對象有無變化,重復以上操作
由於這個EGH並沒有和RootSet有直接或是間接的關系,所以就會被清除。
7、收集所有白色對象(垃圾)
所以我們可以看出這裡的情況,隻要是和root set根集合直接相關的對象或是間接相關的對象都不會被清楚。隻有不相關的才會被回收。
參考文檔:
一張圖講解GC
關於write-barrier寫屏障
以上就是Go語言七篇入門教程GC垃圾回收三色標記的詳細內容,更多關於Go語言GC垃圾回收三色標記的資料請關註WalkonNet其它相關文章!
如何學習Go
如果你是小白,你可以這樣學習Go語言~
七篇入門Go語言
第一篇:Go簡介初識
第二篇:程序結構&&數據類型的介紹
第三篇:函數方法接口的介紹
第四篇:通道與Goroutine的並發編程
第五篇:文件及包的操作與處理
第六篇:網絡編程