Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Safe In Value Receiver In Go

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

When I call m.foo(), as we know , there is a copy of "m",value copy ,which is done by compiler 。 My question is , is there a race in the procedure? It is some kind of reading data from the var "m", I mean , you may need a read lock in case someone is inserting values into m.data when you are copying something from m.data.

If it is thread-safe , is it guarenteed by compiler?

like image 450
frank.lin Avatar asked Nov 01 '22 19:11

frank.lin


1 Answers

This is not safe, and there is no implied safe concurrent access in the language. All concurrent data access is unsafe, and needs to be protected with channels or locks.

Because maps internally contain references to the data they contain, even as the outer structure is copied the map still points to the same data. A concurrent map is often a common requirement, and all you need to do is add a mutex to protect the reads and writes. Though a Mutex pointer would work with your value receiver, it's more idiomatic to use a pointer receiver for mutating methods.

type MyMap struct {
    sync.Mutex
    data map[int]int
}

func (m *MyMap) foo() {
    m.Lock()
    defer m.Unlock()
    //insert  or read from m.data
}

The go memory model is very explicit, and races are generally very easy to reason about. When in doubt, always run your program or tests with -race.

like image 184
JimB Avatar answered Nov 15 '22 17:11

JimB