sum numbers concurrently code review

polaris · · 496 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi I trying to figure out what and when i should use the first approach </p> <pre><code> nums := []int{1, 2, 43} var wg sync.WaitGroup wg.Add(len(nums)) var sum int for _, n := range nums { go func(n int) { defer wg.Done() sum = sum + n }(n) } wg.Wait() fmt.Println(&#34;sum is &#34;, sum) </code></pre> <p>and when the second approach that include channels </p> <pre><code> nums := []int{1, 2, 43} messages := make(chan int) var wg sync.WaitGroup wg.Add(len(nums)) var sum int for _, n := range nums { go func(n int) { defer wg.Done() messages &lt;- n }(n) } go func() { for i := range messages { sum = sum + i } }() wg.Wait() fmt.Println(&#34;the sum is &#34;, sum) </code></pre> <p>Both ways are concurrent if im not wrong ? </p> <hr/>**评论:**<br/><br/>bbrazil: <pre><p>In the former, you&#39;ve multiple threads accessing and mutating <code>sum</code>, so you&#39;ll have race conditions. Using channels avoids this, as would a mutex.</p> <p><a href="https://golang.org/ref/mem" rel="nofollow">https://golang.org/ref/mem</a> has the full details.</p></pre>Ainar-G: <pre><p>Both of your examples seem to have data races. In the first, <code>sum</code> may be overwritten twice. In the second, you don&#39;t actually wait for the summing goroutine, so the vaule of <code>sum</code> when you&#39;re printing it is undefined.</p> <p>When learning to write concurrent code, <em>always</em> use the <a href="https://golang.org/doc/articles/race_detector.html" rel="nofollow">race detector</a>.</p> <p>In your first example, protect the <code>sum</code> with a <code>sync.Mutex</code> or a similar synchronisation mechanism. In your second example, add the summing goroutine to the wait group.</p></pre>bbrazil: <pre><blockquote> <p>In your second example, add the summing goroutine to the wait group.</p> </blockquote> <p>You&#39;d also need to close the channel once the first set of goroutines are complete, so what you&#39;d want is the <code>wg.Wait()</code> and <code>close(messages)</code> in a goroutine, and move the <code>for</code> into the main body of the code.</p></pre>jerf: <pre><p>As one other note, since I&#39;ve seen this problem mentioned on <a href="/r/golang" rel="nofollow">/r/golang</a> a few other times before, bear in mind that processors take basically one cycle to add a number, and that as cheap as goroutines and channels may be, they&#39;re substantially more than &#34;one cycle&#34;. You will see massive <em>slowdown</em> trying to do this concurrently.</p> <p>In fact you basically can&#39;t get any concurrent speedup simply adding integers, because one processor can easily keep up with the entire memory bandwidth from your memory bus if all it has to do is add integers.</p> <p>Again, I know you didn&#39;t ask, but it comes up pretty frequently.</p></pre>613style: <pre><p>Here&#39;s another way to do it without data races. Start some number of concurrent summers, let them all share the input source, and then merge their results.</p> <p><a href="http://play.golang.org/p/oKtq8GoI73" rel="nofollow">http://play.golang.org/p/oKtq8GoI73</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

496 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传