微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Go中创建新的Mutex是否安全?

如何解决在Go中创建新的Mutex是否安全?

我在Go中有一个包含互斥量的结构,我想确保该互斥量永远不会为nil。为此,我实现了一个GetMutex()函数,该函数检查互斥对象是否为nil,如果互斥对象是否为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()
}

解决方法

否,如果同时从多个goroutine中调用Counter.GetMux()是不安全的:GetMux()会同时读写Counter.mux字段。

通常的方法是使用类似“构造函数”的函数来处理初始化,如下所示:

func NewCounter() *Counter {
    return &Counter{
        mux: &sync.Mutex{},}
}

当然,总是使用此NewCounter()创建计数器。

另一种受限方式是使用非指针互斥量值:

type Counter struct {
    mux     sync.Mutex
    counter int
}

因此,当您有一个Counter结构值时,根据设计,它包含一个互斥体。但是,如果执行此操作,则Counter应该始终用作指针,并且Counter结构值不得复制(否则互斥量字段也将被复制,而应复制为{{3 }}指出:“不应复制包含此程序包中定义的类型的值。” )。

此方法的明显优点是Counter的{​​{3}}是一个有效的就绪计数器(自定义类型应该针对此计数器),不需要构造函数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。