Hi all,
I have a wrapper struct around map to provide thread safety. See:
import "sync"
type struct MyMap {
Data map[string]string
sync.RWMutex
}
func (s *MyMap) Set(key string, value string) {
s.Lock()
s.Data[key] = value
s.Unlock()
}
func (s *MyMap) Get(key string) string {
s.RLock()
defer s.RUnlock()
return s.Data[key]
}
Nothing special, I bet most of you have this kind of data structure in your codebase.
In Go 1.6, s.RLock(); defer s.RUnlock()
no longer protect me from race condition. What am I missing?
UPDATE:
The answer is that I was sharing the map in All()
method instead of copying.
评论:
allhatenocattle:
pinpinbo:For this type of struct, why is the Data field being exported? It seems like you might be accidentally accessing Data directly somewhere without using Set/Get. I am also curious to see the actual error and source code that demonstrates the problem.
dgryski:Sorry for the delayed response.
Great point, I'll change it to private and run
-race
again, see what I stumble next.
dgryski:I agree that looks like it should work. Can you produce an entire program that demonstrates the issue? Is there a race somewhere else? What does the race detector say?
pinpinbo:Also, please run go vet and make sure you're never passing a MyMap by value.
earthboundkid:Sorry for the delayed response:
You can see the full library here: https://github.com/resourced/resourced/blob/master/libmap/libmap.go
I captured the
-race
stack trace here: https://gist.github.com/didip/bd8b49f6b18fa6ee4190Nothing surprising, typical race problem: 1 thread tries to set() and the other one tries to get()
go vet
does not return anything.
pinpinbo:
All
returns the original map, not a copy, thereby bypassing all locks. You need to grab the lock and do a full copy instead.
danielt0shea:Yup, this is the answer. I was sharing map instead of copying. Thanks!
pinpinbo:Is it possible that you call NewTSafeMapCounter with an existing map parameter and the map is used by two go-routines?
danielt0shea:Yup, this is the answer. I was sharing map instead of copying. Thanks!
If you run the race detector what does it say?