我在 Go 中有一个包含互斥锁的结构,我想确保该互斥锁从不nil。为此,我实现了一个GetMutex()函数,它检查互斥锁是否为 nil,如果是,则为其分配一个值。我的问题是:以下代码线程安全吗?如果不是,那么确保mux始终初始化的惯用方法是什么?我唯一能想到的就是在这个包中有一个全局互斥锁,它在我的GetMutex()函数中使用,但也许有不同的方法。package mainimport ( "sync")type Counter struct { mux *sync.Mutex counter int}// Is this thread safe?func (c *Counter) GetMux() *sync.Mutex { if c.mux == nil { c.mux = &sync.Mutex{} } return c.mux}func (c *Counter) Inc() { c.GetMux().Lock() c.counter++ c.GetMux().Unlock()}func main() { c := &Counter{} c.Inc()}
1 回答
子衿沉夜
TA贡献1828条经验 获得超3个赞
Counter.GetMux()不,如果同时从多个 goroutine 调用它是不安全的:GetMux()同时读取和写入Counter.mux字段。
一般的方法是使用类似“构造函数”的函数来处理初始化,如下所示:
func NewCounter() *Counter {
return &Counter{
mux: &sync.Mutex{},
}
}
当然,总是用 this 创建计数器NewCounter()。
另一种有限的方法是使用非指针互斥值:
type Counter struct {
mux sync.Mutex
counter int
}
因此,当您有一个Counter结构值时,它——按照设计——包括一个互斥体。但是,如果您这样做,Counter则应始终将其用作指针,并且Counter不得复制结构值(否则互斥锁字段也将被复制,但作为包文档的sync状态:“包含此包中定义的类型的值不应被复制。”)。
这样做的明显优势是零值是Counter一个有效且准备好的计数器(您应该针对您的自定义类型),并且不需要构造函数。
- 1 回答
- 0 关注
- 97 浏览
添加回答
举报
0/150
提交
取消