面試官:Context攜帶數(shù)據(jù)是線程安全的嗎?
本文轉(zhuǎn)載自微信公眾號(hào)「Golang夢(mèng)工廠」,作者AsongGo。轉(zhuǎn)載本文請(qǐng)聯(lián)系Golang夢(mèng)工廠公眾號(hào)。
哈嘍,大家好,我是asong。最近一個(gè)群里看到一個(gè)有趣的八股文,問(wèn)題是:使用context攜帶的value是線程安全的嗎?這道題其實(shí)就是考察面試者對(duì)context實(shí)現(xiàn)原理的理解,如果不知道context的實(shí)現(xiàn)原理,很容易答錯(cuò)這道題,所以本文我們就借著這道題,再重新理解一遍context攜帶value的實(shí)現(xiàn)原理。
context攜帶value是線程安全的嗎?
先說(shuō)答案,context本身就是線程安全的,所以context攜帶value也是線程安全的,寫(xiě)個(gè)簡(jiǎn)單例子驗(yàn)證一下:
func main() {
ctx := context.WithValue(context.Background(), "asong", "test01")
go func() {
for {
_ = context.WithValue(ctx, "asong", "test02")
}
}()
go func() {
for {
_ = context.WithValue(ctx, "asong", "test03")
}
}()
go func() {
for {
fmt.Println(ctx.Value("asong"))
}
}()
go func() {
for {
fmt.Println(ctx.Value("asong"))
}
}()
time.Sleep(10 * time.Second)
}
程序正常運(yùn)行,沒(méi)有任何問(wèn)題,接下來(lái)我們就來(lái)看一下為什么context是線程安全的!!!
為什么線程安全?
context包提供兩種創(chuàng)建根context的方式:
- context.Backgroud()
- context.TODO()
又提供了四個(gè)函數(shù)基于父Context衍生,其中使用WithValue函數(shù)來(lái)衍生context并攜帶數(shù)據(jù),每次調(diào)用WithValue函數(shù)都會(huì)基于當(dāng)前context衍生一個(gè)新的子context,WithValue內(nèi)部主要就是調(diào)用valueCtx類(lèi):
func WithValue(parent Context, key, val interface{}) Context {
if parent == nil {
panic("cannot create context from nil parent")
}
if key == nil {
panic("nil key")
}
if !reflectlite.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &valueCtx{parent, key, val}
}
valueCtx結(jié)構(gòu)如下:
type valueCtx struct {
Context
key, val interface{}
}
valueCtx繼承父Context,這種是采用匿名接口的繼承實(shí)現(xiàn)方式,key,val用來(lái)存儲(chǔ)攜帶的鍵值對(duì)。
通過(guò)上面的代碼分析,可以看到添加鍵值對(duì)不是在原context結(jié)構(gòu)體上直接添加,而是以此context作為父節(jié)點(diǎn),重新創(chuàng)建一個(gè)新的valueCtx子節(jié)點(diǎn),將鍵值對(duì)添加在子節(jié)點(diǎn)上,由此形成一條context鏈。
獲取鍵值過(guò)程也是層層向上調(diào)用直到最終的根節(jié)點(diǎn),中間要是找到了key就會(huì)返回,否會(huì)就會(huì)找到最終的emptyCtx返回nil。畫(huà)個(gè)圖表示一下:
image-20220207214507921
總結(jié):context添加的鍵值對(duì)一個(gè)鏈?zhǔn)降模瑫?huì)不斷衍生新的context,所以context本身是不可變的,因此是線程安全的。
總結(jié)
本文主要是想帶大家回顧一下context的實(shí)現(xiàn)原理,面試中面試官都喜歡隱晦提出問(wèn)題,所以這就需要我們有很扎實(shí)的基本功,一不小心就會(huì)掉入面試官的陷阱,要處處小心哦~
好啦,本文到這里就結(jié)束了,我是asong,我們下期見(jiàn)。
創(chuàng)建了讀者交流群,歡迎各位大佬們踴躍入群,一起學(xué)習(xí)交流。入群方式:關(guān)注公眾號(hào)獲取。更多學(xué)習(xí)資料請(qǐng)到公眾號(hào)領(lǐng)取。