[Newbie Question] Why do you need to lock when setting up tcp and https listener

polaris · · 428 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I see this in open source library sometimes</p> <pre><code>func (struct *myStruct) Main() { tcpListener, err := net.Listen(&#34;tcp&#34;, struct.getOpts().TCPAddress) struct.Lock() struct.tcpListener = tcpListener struct.Unlock() httpsListener, err = tls.Listen(&#34;tcp&#34;, struct.getOpts().HTTPSAddress, struct.tlsConfig) struct.Lock() struct.httpsListener = httpsListener struct.Unlock() } </code></pre> <p>Is it idiomatic to lock when setting up listener for tcp and https in main for golang, what kind of situation will you reach race condition?</p> <hr/>**评论:**<br/><br/>peterbourgon: <pre><p>Locking is necessary when multiple goroutines may be accessing the struct (or, more accurately, its members) concurrently. But without more context, this is not good code, because you generally shouldn&#39;t be manually calling Lock and Unlock like this. Where did you find this code?</p></pre>Thaxll: <pre><p>There: <a href="https://github.com/nsqio/nsq/blob/master/nsqd/nsqd.go#L209" rel="nofollow">https://github.com/nsqio/nsq/blob/master/nsqd/nsqd.go#L209</a></p></pre>jerf: <pre><p>Examining this code, I don&#39;t think the locks are necessary. It doesn&#39;t look to me like the <code>Main()</code> function they are embedded in is expected to be re-entrant, so normally I&#39;d expect that this is using, for lack of a better term, the &#34;initialize read-only and-then multithread&#34; pattern. That is, it is common (I find) in Go for a particular goroutine to set up a struct without using locks on the struct and without sharing that struct, and then for there to be a single point at which all that initialization is done and then the struct is multi-threading safe, because all the values are read-only after that point and therefore don&#39;t need locks. In that case I wouldn&#39;t expect <code>Main()</code> here to be using locks, because at that point I would expect that only one goroutine could possibly be running.</p> <p>Part of the reason I expect that is that otherwise that code above is, if not wrong, at least very dangerous. If multiple things are running through <code>Main()</code> at once, that code above runs the risk of having the tcpListener from one goroutine win, while the httpsListener from another goroutine wins. Because of the fact that listening ports are themselves a sort of a lock (as the OS enforces that) and the fact the rest of the code in that function will <code>os.Exit(1)</code> if acquiring the port fails (which is reasonable on its own for a server), I infer that in practice multiple goroutines are not running through this code as that would cause the program to fail intermittently, but routinely, at startup.</p> <p>Personally, I&#39;d remove those locks and document more clearly what is being used when. You could justify the use of locks that way with a handwave at being paranoid, but I&#39;d personally rather see it correct and well-documented than merely paranoid. YMMV (no sarcasm; there&#39;s a time and a place for paranoia).</p></pre>glhfggkkthxbye: <pre><p>I don&#39;t totally agree with the code, but the locking is fine. The locks are encapsulated within the struct. The code creates a new listener, and upon successful creation locks a race vulrenable resource(the resources encapsulated in the struct), then assigns the listener to the struct, and unlocks - all the functionality is contained within the struct.</p> <p>Why add another wrapper func within this initialization func? For more overhead? Or for more indirection?</p></pre>

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

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