为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中创建新的 Mutex 是线程安全的吗?

在 Go 中创建新的 Mutex 是线程安全的吗?

Go
梦里花落0921 2022-07-11 10:23:04
我在 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一个有效且准备好的计数器(您应该针对您的自定义类型),并且不需要构造函数。


查看完整回答
反对 回复 2022-07-11
  • 1 回答
  • 0 关注
  • 97 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信