<p>Hi all,</p>
<p>I have a wrapper struct around map to provide thread safety. See:</p>
<pre><code>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]
}
</code></pre>
<p>Nothing special, I bet most of you have this kind of data structure in your codebase.</p>
<p>In Go 1.6, <code>s.RLock(); defer s.RUnlock()</code> no longer protect me from race condition. What am I missing?</p>
<p><strong>UPDATE:</strong>
The answer is that I was sharing the map in <code>All()</code> method instead of copying.</p>
<hr/>**评论:**<br/><br/>allhatenocattle: <pre><p>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. </p></pre>pinpinbo: <pre><p>Sorry for the delayed response.</p>
<p>Great point, I'll change it to private and run <code>-race</code> again, see what I stumble next.</p></pre>dgryski: <pre><p>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?</p></pre>dgryski: <pre><p>Also, please run go vet and make sure you're never passing a MyMap by value. </p></pre>pinpinbo: <pre><p>Sorry for the delayed response:</p>
<p>You can see the full library here: <a href="https://github.com/resourced/resourced/blob/master/libmap/libmap.go" rel="nofollow">https://github.com/resourced/resourced/blob/master/libmap/libmap.go</a></p>
<p>I captured the <code>-race</code> stack trace here: <a href="https://gist.github.com/didip/bd8b49f6b18fa6ee4190" rel="nofollow">https://gist.github.com/didip/bd8b49f6b18fa6ee4190</a></p>
<p>Nothing surprising, typical race problem: 1 thread tries to set() and the other one tries to get()</p>
<p><code>go vet</code> does not return anything.</p></pre>earthboundkid: <pre><p><code>All</code> returns the original map, not a copy, thereby bypassing all locks. You need to grab the lock and do a full copy instead. </p></pre>pinpinbo: <pre><p>Yup, this is the answer. I was sharing map instead of copying. Thanks!</p></pre>danielt0shea: <pre><p>Is it possible that you call NewTSafeMapCounter with an existing map parameter and the map is used by two go-routines?</p></pre>pinpinbo: <pre><p>Yup, this is the answer. I was sharing map instead of copying. Thanks!</p></pre>danielt0shea: <pre><p>If you run the race detector what does it say?</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传