为什么 Go stdlib 使用互斥锁来读取上下文的错误字段?

Why does Go stdlib use a mutually exclusive lock to read context's error field?

提问人:Ivan Velichko 提问时间:7/17/2022 最后编辑:TylerHIvan Velichko 更新时间:7/18/2022 访问量:107

问:

Go 标准库中有许多接口的底层实现。例如,和上下文由未公开的类型支持,该类型本质上只是使用一些存根方法(证明)。同样,每次调用都会返回该类型的实例,该实例已经是具有一堆互斥锁保护属性(proof)的正确结构:ContextBackgroundTODOemptyCtxintcontext.WithCancel()cancelCtx

// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
    Context

    mu       sync.Mutex            // protects following fields
    done     atomic.Value          // of chan struct{}, created lazily, closed by first cancel call
    children map[canceler]struct{} // set to nil by the first cancel call
    err      error                 // set to non-nil by the first cancel call
}

为什么结构体使用互斥锁而不是 ?例如,该方法当前获取了一个完全锁,而它(可能)可能只使用一个:cancelCtxRWLockErr()RLock

func (c *cancelCtx) Err() error {
    c.mu.Lock()
    err := c.err
    c.mu.Unlock()
    return err
}
GO LOCKING 互斥 锁标准库

评论

3赞 Peter 7/17/2022
你必须要求作者确定(你可以,使用邮件列表),但一个很好的猜测是,因为 RWMutex 的大小是互斥锁的三倍,而且上下文值无处不在,所以实际程序中的读写比率需要高得多才能进行权衡。现在我想起来,我什至不相信读取比写入更频繁。

答:

2赞 Kassian Sun 7/17/2022 #1

原因之一应该是性能不佳RWLock

锁的性能不取决于它提供的功能,而是取决于底层。虽然理论上可以提供更高的,但对于这种特定场景(改变一个微小的变量),可以提供更低的。implementationRWLockthroughputsMutexunnecessary overhead