【问题标题】:Thread Safe In Value Receiver In GoGo中的线程安全值接收器
【发布时间】:2014-07-29 22:18:55
【问题描述】:
type MyMap struct {

     data map[int]int

}
func (m Mymap)foo(){

    //insert  or read from m.data

}
...
   go func f  (m *Mymap){
         for {
            //insert into m.data 
         }
   }()
...
Var m Mymap

m.foo()

当我调用 m.foo() 时,我们知道,有一个“m”的副本,值副本,这是由编译器完成的。我的问题是,程序中是否存在竞争?这是从 var "m" 读取数据的某种方式,我的意思是,当您从 m.data 复制某些内容时,您可能需要一个读取锁,以防有人在 m.data 中插入值。

如果是线程安全的,编译器是否保证?

【问题讨论】:

    标签: go thread-safety


    【解决方案1】:

    这是不安全的,并且该语言中没有隐含的安全并发访问。所有并发数据访问都是不安全的,需要使用通道或锁进行保护。

    因为地图内部包含对其所含数据的引用,即使复制了外部结构,地图仍然指向相同的数据。并发映射通常是一个常见的需求,您需要做的就是添加一个互斥锁来保护读取和写入。虽然 Mutex 指针可以与您的值接收器一起使用,但使用指针接收器来更改方法更为惯用。

    type MyMap struct {
        sync.Mutex
        data map[int]int
    }
    
    func (m *MyMap) foo() {
        m.Lock()
        defer m.Unlock()
        //insert  or read from m.data
    }
    

    go memory model 非常明确,种族通常很容易推理。如有疑问,请始终使用-race 运行您的程序或测试。

    【讨论】:

    • 如果 MyMap 有一个字段 foo string 或 int,或者 string 或 int 的指针,它在同时分配新值之前是否需要锁定?我的意思是你锁定它是因为字段 data 是类型映射或需要保护所有 MyMap 字段。
    • @ChinglinWen:你使用互斥锁来保护地图,地图包含什么类型无关紧要。这并不意味着您可能不需要在其他地方进行额外的同步,但这超出了问题的范围。
    猜你喜欢
    • 2012-07-11
    • 2015-06-30
    • 2021-06-20
    • 2013-11-07
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    相关资源
    最近更新 更多