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

我在 Go 中有一个包含互斥锁的结构,我想确保该互斥锁从不nil。为此,我实现了一个GetMutex()函数,它检查互斥锁是否为 nil,如果是,则为其分配一个值。


我的问题是:以下代码线程安全吗?如果不是,那么确保mux始终初始化的惯用方法是什么?我唯一能想到的就是在这个包中有一个全局互斥锁,它在我的GetMutex()函数中使用,但也许有不同的方法。


package main


import (

    "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()

}


梦里花落0921
浏览 100回答 1
1回答

子衿沉夜

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一个有效且准备好的计数器(您应该针对您的自定义类型),并且不需要构造函数。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go