<p>The title is pretty self-explanatory. I have a map from <code>string</code> to callback functions which could potentially be accessed concurrently, but each goroutine has its own unique map key in scope, effectively guaranteeing that they won't be stepping on each other's toes, since each one has a unique id and only accesses the map using that id. Is it still necessary to synchronize map access with a mutex, or can I skip it?</p>
<hr/>**评论:**<br/><br/>jerf: <pre><p>If they are writing to the map, they must synchronize.</p>
<p>If they are only concurrently reading, you are safe. But be <em>sure</em> there's a phase where you are non-concurrently writing, then a clear transition to concurrent reading, and nothing in between.</p>
<p>However, I'd also be curious as to what you are doing. Between arguments you can pass in to the goroutine and closure arguments you can implicitly pass in, it sounds strange that you would access a map to get a unique key when the goroutine might have a way of simply having the value in hand. Perhaps the real solution involves getting rid of this map entirely, or failing that, factoring the map read out into one event prior to the goroutine's creation.</p></pre>TheMerovius: <pre><blockquote>
<p>If they are only concurrently reading, you are safe.</p>
</blockquote>
<p>This is strictly speaking incorrect, AFAIK. While the <em>current</em> map implementation by the gc toolchain allows this, there is no such guarantee made by the language spec and as such that can a) change at any future go version and b) might not work for different compilers (think gopherjs and other third-party compilers, not so much gccgo).</p>
<p>Apart from that, a big +1 for the rest of your answer. If the map is never written, it is superfluous and shouldn't exist. If the map is ever written, accessing it without locking is definitely unsafe.</p></pre>jerf: <pre><p>First, as a pragmatic matter, a map implementation that was unsafe to concurrently read with no writes would be very strange, it would almost have to be written to produce such a result on purpose.</p>
<p>Secondly, if you do basically this (give or take some intervening functions, etc.):</p>
<pre><code> theMap := map[string]func()
theMap["a"] = func(){...}
theMap["b"] = func(){...}
go func() { ... }
go func() { ... }
go somethingElse(theMap)
</code></pre>
<p>I'm fairly sure the <a href="https://golang.org/ref/mem">memory model</a> means that all the goroutines are guaranteed to see the fully constructed map (the "go" statement is guaranteed to be sequenced before the functions begin execution, see the "Goroutine creation" section), and there's nothing else in that document that I can see that suggests concurrent reads would be unsafe.</p>
<p>If you followed the <code>go</code> statements with another setting of <code>theMap</code>, you would be in trouble. Map setting is not atomic, even at the language level. Other readers and writers can observe a half-updated map, unto panic/segfault.</p></pre>TheMerovius: <pre><blockquote>
<p>First, as a pragmatic matter, a map implementation that was unsafe to concurrently read with no writes would be very strange</p>
</blockquote>
<p>Not really. For example you could put a small cache in front of a large map, to speed up access. You could implement the map as a rebalancing search tree that makes often accessed elements faster to fetch. You could do all kinds of micro-optimizations that require this.</p>
<p>However, I take my statement back, I remembered <a href="https://groups.google.com/forum/#!searchin/golang-nuts/concurrent$20read$20from$20map/golang-nuts/3FVAs9dPR8k/SAOJlRQDx2AJ" rel="nofollow">this thread</a> ending differently (and it very clearly states that concurrent reads are correct).</p></pre>mwholt: <pre><p>Maps have a header and allocate memory under the hood to make room for new entries, even if you guarantee that each goroutine uses a different key. So if two goroutines each try to add a new entry to the map at the same time, even though they have different keys, it's a race condition.</p>
<p>If they are only reading, you're fine, but once there is a write, it must be the only action on the map at that time. You can use a RWMutex to help ensure this.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传