原文链接:面试官:Context携带数据是线程平安的吗?

前言

asongcontextvaluecontextcontextcontextvalue
contextvalue
contextcontextvalue
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)
}
contextcontext
func main()  {
    m := make(map[string]string)
    m ["asong"] = "Golang梦工厂"
    ctx := context.WithValue(context.Background(), "asong", m)
    go func() {
        for {
            m1 := ctx.Value("asong")
            mm := m1.(map[string]string)
            mm["asong"] = "123213"
        }
    }()
    go func() {
        for {
            m1 := ctx.Value("asong")
            mm := m1.(map[string]string)
            mm["asong"] = "123213"
        }
    }()
    time.Sleep(10 * time.Second)
}

运行后果:

fatal error: concurrent map writes

goroutine 18 [running]:
runtime.throw({0x1072af2, 0x0})
......

为什么线程平安?

contextcontext
context.Backgroud()context.TODO()
ContextWithValuecontextWithValuecontextcontextWithValuevalueCtx
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
type valueCtx struct {
 Context
 key, val interface{}
}
valueCtxContextkey,val
contextcontextvalueCtxcontext
keyemptyCtxnil

画个图示意一下:

contextcontextcontext

总结

context

好啦,本文到这里就完结了,我是asong,咱们下期见。

欢送关注公众号:【Golang梦工厂】