自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 細節(jié)篇|內(nèi)存回收又踩坑了

開發(fā) 前端 數(shù)據(jù)管理
那么什么是 Finalizer 機制呢?這個就必須要再提一嘴 Go 的 GC 機制了。這個是 Go 比較有特色的機制。在 Go 里程序員負責(zé)申請內(nèi)存,Go 的 runtime 的 GC 機制負責(zé)回收。

 背景提要

分享一個 GC 相關(guān)的踩坑實踐。公司線上某組件內(nèi)存資源泄漏,偶發(fā) oom 。通過 Go 的 pprof 排查,很快速定位到泄漏的數(shù)據(jù)結(jié)構(gòu) A ,結(jié)構(gòu) A 的相關(guān)資源是通過 Go 的 Finalizer 機制來釋放的。但詭異的來了,對照著代碼審視了多次之后,大家一致斷定,這段代碼絕對沒有泄漏的問題。但是,事實勝于雄辯,現(xiàn)實就是泄漏就在此處。想不通。。。

幾天之后,問題的轉(zhuǎn)機來自于另一個毫不相關(guān)的地方,我們發(fā)現(xiàn)了一個卡住的協(xié)程。最開始并不在意,因為雖然卡住是異常的,但是泄漏的地點差了十萬八千里,兩者毫不相關(guān)。所以剛開始是忽略的。

后來實在是想不開,閑來無事,把這個異常點拿來看,才發(fā)現(xiàn)一點點線索。這個卡住的協(xié)程是一個結(jié)構(gòu)體 B 的釋放過程,和 A 一樣也是 Go 的 Finalizer 機制。我們踩的坑就于此有關(guān),很典型,出人意料,所以分享給大家。先復(fù)習(xí)一下 Finalizer 機制。

什么是 Go 的 Finalizer 機制?

那么什么是 Finalizer 機制呢?這個就必須要再提一嘴 Go 的 GC 機制了。這個是 Go 比較有特色的機制。在 Go 里程序員負責(zé)申請內(nèi)存,Go 的 runtime 的 GC 機制負責(zé)回收。

在這個過程,Go 語言還提供了一個 Finalizer 機制,允許程序員在申請的時候指定一個回調(diào)函數(shù),在 GC 回收到這個結(jié)構(gòu)體內(nèi)存的時候,Go 會自動調(diào)用一次這個回調(diào)函數(shù)。

func SetFinalizer(obj interface{}, finalizer interface{})

這個非常實用的一個技巧,在文章《??編程思考:對象生命周期的問題??》里有分享。主要是比較安全的解決掉對象聲明周期的問題。因為程序員自己來管理資源的釋放,那很可能出 bug ,比如在有人用的時候調(diào)用釋放。通過 Finalizer 機制,則能保證一定是無人引用的結(jié)構(gòu)體內(nèi)存,才會執(zhí)行回調(diào)。

舉個例子:

type TestStruct struct {
name string
}

//go:noinline
func newTestStruct() *TestStruct {
v := &TestStruct{"n1"}
runtime.SetFinalizer(v, func(p *TestStruct) {
fmt.Println("gc Finalizer")
})
return v
}

func main() {
t := newTestStruct()
fmt.Println("== start ===")
_ = t
fmt.Println("== ... ===")
runtime.GC()
fmt.Println("== end ===")
}

上面的例子,給結(jié)構(gòu)體 TestStruct 的釋放設(shè)置了一個 Finalizer 回調(diào)函數(shù)。然后在主動調(diào)用 runtime.GC 來快速回收,童鞋可以體驗一下。

Finalizer 這里竟然有個坑?

Finalizer 很好用這是事實,但 Finalizer 機制也有限制條件,在官網(wǎng)上有如下聲明:

A single goroutine runs all finalizers for a program, sequentially. If a finalizer must run for a long time, it should do so by starting a new goroutine.

來自 https://golang.google.cn/pkg/runtime/#SetFinalizer ,什么意思?

說得是,Go 的 runtime 是用一個單 goroutine 來執(zhí)行所有的 Finalizer 回調(diào),還是串行化的。

劃重點:一旦執(zhí)行某個 Finalizer 出了問題,可能會影響到全局的 Finalizer 回調(diào)函數(shù)的執(zhí)行。

原來如此?。?/p>

我們這次就是精準踩坑。在釋放 B 結(jié)構(gòu)體的時候,調(diào)用了一個 Finalizer 回調(diào),然后把協(xié)程卡死了。導(dǎo)致后續(xù)所有的 Finalizer 回調(diào)都執(zhí)行不了,比如 A 的 Finalizer 就無法執(zhí)行,從而導(dǎo)致資源的泄漏和各種的異常。

舉個例子:

var (
done chan struct{}
)

type A struct {
name string
}

type B struct {
name string
}

type C struct {
name string
}

func newA() *A {
v := &A{"n1"}
runtime.SetFinalizer(v, func(p *A) {
fmt.Println("gc Finalizer A")
})
return v
}

func newB() *B {
v := &B{"n1"}
runtime.SetFinalizer(v, func(p *B) {
<-done
fmt.Println("gc Finalizer B")
})
return v
}

func newC() *C {
v := &C{"n1"}
runtime.SetFinalizer(v, func(p *C) {
fmt.Println("gc Finalizer C")
})
return v
}

func main() {
a := newA()
b := newB()
c := newC()
fmt.Println("== start ===")
_, _, _ = a, b, c
fmt.Println("== ... ===")
for i := 0; i < 10; i++ {
runtime.GC()
}
fmt.Println("== end ===")
}

這里創(chuàng)建了一個極簡的例子,A,B, C 實例都設(shè)置了 Finalizer 回調(diào),故意讓其中一個阻塞住,會影響到剩下的 Finalizer 的執(zhí)行。

總結(jié)

  1. Go 提供的 Finalizer 機制,讓程序員創(chuàng)建的時候注冊回調(diào)函數(shù),能很好的幫助程序員解決資源安全釋放的問題;
  2. Finalizer 的執(zhí)行是全局單協(xié)程,且串行化執(zhí)行的。所以可能會因為某一次的卡住導(dǎo)致全局的失效,切記;
  3. 排查內(nèi)存問題的時候,pprof 看現(xiàn)場很明確,但是根因可能是看似毫不相關(guān)的旮旯角落,有時候要把思維跳出來排查;
責(zé)任編輯:武曉燕 來源: 奇伢云存儲
相關(guān)推薦

2022-11-18 07:34:12

Docker項目目錄

2024-04-10 08:39:56

BigDecimal浮點數(shù)二進制

2021-09-09 18:12:22

內(nèi)存分段式網(wǎng)絡(luò)

2021-10-28 19:10:02

Go語言編碼

2010-01-06 10:36:00

.NET Framew

2024-04-01 08:05:27

Go開發(fā)Java

2020-09-29 07:57:48

設(shè)置HttpClientContent-Typ

2020-09-06 10:02:32

項目管理戰(zhàn)略目標(biāo)CIO

2021-10-08 11:05:00

Go 切片內(nèi)存

2023-03-13 13:36:00

Go擴容切片

2016-12-20 14:30:40

2016-12-20 14:38:26

2018-09-30 15:37:07

數(shù)據(jù)庫MySQLMyCat

2022-04-26 21:49:55

Spring事務(wù)數(shù)據(jù)庫

2021-07-28 05:01:29

Lombok前端測試

2024-11-20 18:16:39

MyBatis批量操作數(shù)據(jù)庫

2020-12-22 09:34:20

JavaScript開發(fā)技術(shù)

2023-01-18 23:20:25

編程開發(fā)

2020-09-15 08:46:26

Kubernetes探針服務(wù)端

2025-02-26 12:06:07

點贊
收藏

51CTO技術(shù)棧公眾號