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

huangapple go评论76阅读模式
英文:

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

问题

在Go标准库中,有一些对Context接口的底层实现。例如,BackgroundTODO上下文是由未公开的emptyCtx类型支持的,该类型实质上只是带有一些存根方法的int类型(证明)。同样,每次调用context.WithCancel()都会返回一个cancelCtx类型的实例,该类型已经是一个合适的结构体,具有一些受互斥锁保护的属性(证明):

// cancelCtx可以被取消。当取消时,它也会取消任何实现了canceler接口的子上下文。
type cancelCtx struct {
    Context

    mu       sync.Mutex            // 保护以下字段
    done     atomic.Value          // chan struct{}的实例,延迟创建,在第一次取消调用时关闭
    children map[canceler]struct{} // 在第一次取消调用时设置为nil
    err      error                 // 在第一次取消调用时设置为非nil
}

为什么cancelCtx结构使用互斥锁而不是RWLock?例如,Err()方法当前获取了一个完整的锁,而它(可能)只需要使用一个读锁:

func (c *cancelCtx) Err() error {
    c.mu.Lock()
    err := c.err
    c.mu.Unlock()
    return err
}
英文:

There are a number of under-the-hood implementations of the Context interface in the Go standard library. For instance, the Background and TODO contexts are backed by the unexposed emptyCtx type which is essentially just int with some stub methods (proof). Similarly, every call to context.WithCancel() returns an instance of the cancelCtx type which is already a proper struct with a bunch of mutex-protected attributes (proof):

// 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
}

Why does the cancelCtx struct use a mutually exclusive lock and not an RWLock? For instance, the Err() method currently acquires a full lock while it (probably) could have used just an RLock:

func (c *cancelCtx) Err() error {
	c.mu.Lock()
	err := c.err
	c.mu.Unlock()
	return err
}

答案1

得分: 2

一个原因可能是 RWLock 性能较差

锁的性能不取决于它提供的功能,而是取决于底层的 实现。尽管从理论上讲,RWLock 可以提供更高的 吞吐量,但对于这个特定的场景(修改一个小变量),Mutex 可能提供更低的 不必要开销

英文:

One reason should be RWLock has poor performance.

The performance of locks doesn't depends on the features it provides, it depends on the underlying implementation. Although theoretically RWLock can provides higher throughputs, for this specific scenario (mutating a tiny variable), Mutex could provide lower unnecessary overhead.

huangapple
  • 本文由 发表于 2022年7月17日 15:49:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/73010059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定