英文:
Why does Go stdlib use a mutually exclusive lock to read context's error field?
问题
在Go标准库中,有一些对Context
接口的底层实现。例如,Background
和TODO
上下文是由未公开的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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论