回到简体

This commit is contained in:
chai2010
2016-02-15 11:06:34 +08:00
parent 9e878f9944
commit 2b37b23285
177 changed files with 2354 additions and 2354 deletions

View File

@@ -1,14 +1,14 @@
### 8.4.1. 不帶緩存的Channels
### 8.4.1. 不带缓存的Channels
個基於無緩存Channels的送操作將導致發送者goroutine阻塞直到另一goroutine在相同的Channels上行接收操作,當發送的值通Channels成功傳輸之後,兩個goroutine可以繼續執行後面的句。反之,如果接收操作先生,那接收者goroutine也阻塞,直到有另一goroutine在相同的Channels上執行發送操作。
个基于无缓存Channels的送操作将导致发送者goroutine阻塞直到另一goroutine在相同的Channels上行接收操作,当发送的值通Channels成功传输之后,两个goroutine可以继续执行后面的句。反之,如果接收操作先生,那接收者goroutine也阻塞,直到有另一goroutine在相同的Channels上执行发送操作。
於無緩存Channels的送和接收操作將導致兩個goroutine做一次同步操作。因爲這個原因,無緩存Channels有候也被稱爲同步Channels。當通過一個無緩存Channels發送數據時,接收者收到數據發生在喚醒發送者goroutine之前譯註*happens before*是Go語言併發內存模型的一個關鍵術語!)。
于无缓存Channels的送和接收操作将导致两个goroutine做一次同步操作。因为这个原因,无缓存Channels有候也被称为同步Channels。当通过一个无缓存Channels发送数据时,接收者收到数据发生在唤醒发送者goroutine之前译注*happens before*是Go语言并发内存模型的一个关键术语!)。
討論併發編程時,當我們説x事件在y事件之前生(*happens before*),我們併不是x事件在時間上比y時間更早;我要表的意思是要保在此之前的事件都已完成了,例如在此之前的更新某些量的操作已完成,你可以放心依賴這些已完成的事件了。
讨论并发编程时,当我们说x事件在y事件之前生(*happens before*),我们并不是x事件在时间上比y时间更早;我要表的意思是要保在此之前的事件都已完成了,例如在此之前的更新某些量的操作已完成,你可以放心依赖这些已完成的事件了。
當我們説x事件不是在y事件之前生也不是在y事件之後發生,我們就説x事件和y事件是併發的。這併不是意味着x事件和y事件就一定是同時發生的,我們隻是不能確定這兩個事件生的先後順序。在下一章中我們將看到,當兩個goroutine併發訪問了相同的變量時,我有必要保某些事件的執行順序,以避免出某些併發問題
当我们说x事件不是在y事件之前生也不是在y事件之后发生,我们就说x事件和y事件是并发的。这并不是意味着x事件和y事件就一定是同时发生的,我们只是不能确定这两个事件生的先后顺序。在下一章中我们将看到,当两个goroutine并发访问了相同的变量时,我有必要保某些事件的执行顺序,以避免出某些并发问题
在8.3的客端程序它在主goroutine中譯註:就是行main函的goroutine將標準輸入複製到server因此當客戶端程序關閉標準輸入時,後台goroutine可能依然在工作。我需要主goroutine等待台goroutine完成工作再退出,我使用了一channel同步兩個goroutine
在8.3的客端程序它在主goroutine中译注:就是行main函的goroutine将标准输入复制到server因此当客户端程序关闭标准输入时,后台goroutine可能依然在工作。我需要主goroutine等待台goroutine完成工作再退出,我使用了一channel同步两个goroutine
<u><i>gopl.io/ch8/netcat3</i></u>
```Go
@@ -29,11 +29,11 @@ func main() {
}
```
當用戶關閉了標準輸主goroutine中的mustCopy函數調用將返迴,然後調用conn.Close()關閉讀和寫方向的網絡連接。關閉網絡鏈接中的方向的鏈接將導致server程序收到一文件end-of-file束的信號。關閉網絡鏈接中方向的鏈接將導致後台goroutine的io.Copy函數調用返迴一個“read from closed connection”從關閉的鏈接讀”)似的錯誤,因此我們臨時移除了錯誤日誌語句;在練習8.3將會提供一更好的解方案。(需要意的是go語句調用了一個函數字面量,Go言中啟動goroutine常用的形式。
当用户关闭了标准输主goroutine中的mustCopy函数调用将返回,然后调用conn.Close()关闭读和写方向的网络连接。关闭网络链接中的方向的链接将导致server程序收到一文件end-of-file束的信号。关闭网络链接中方向的链接将导致后台goroutine的io.Copy函数调用返回一个“read from closed connection”从关闭的链接读”)似的错误,因此我们临时移除了错误日志语句;在练习8.3将会提供一更好的解方案。(需要意的是go语句调用了一个函数字面量,Go言中启动goroutine常用的形式。
台goroutine返之前,它先打印一個日誌信息,然向done對應的channel送一值。主goroutine在退出前先等待done對應的channel接收一值。因此,是可以在程序退出前正確輸出“done”消息。
台goroutine返之前,它先打印一个日志信息,然向done对应的channel送一值。主goroutine在退出前先等待done对应的channel接收一值。因此,是可以在程序退出前正确输出“done”消息。
channels送消息有兩個重要方面。首先每消息都有一值,但是有候通的事實和發生的刻也同重要。當我們更希望強調通訊發生的時刻時,我們將它稱爲**消息事件**。有些消息事件併不攜帶額外的信息,它僅僅是用作兩個goroutine之的同步,這時候我可以用`struct{}`結構體作爲channels元素的型,然也可以使用bool或int類型實現同樣的功能,`done <- 1`句也比`done <- struct{}{}`更短。
channels送消息有两个重要方面。首先每消息都有一值,但是有候通的事实和发生的刻也同重要。当我们更希望强调通讯发生的时刻时,我们将它称为**消息事件**。有些消息事件并不携带额外的信息,它仅仅是用作两个goroutine之的同步,这时候我可以用`struct{}`结构体作为channels元素的型,然也可以使用bool或int类型实现同样的功能,`done <- 1`句也比`done <- struct{}{}`更短。
**練習 8.3** 在netcat3例子中conn然是一interface型的值,但是其底層眞實類型是`*net.TCPConn`,代表一TCP接。一TCP接有讀和寫兩個部分可以使用CloseRead和CloseWrite方法分别關閉它們。脩改netcat3的主goroutine代碼,隻關閉網絡鏈接中的部分,這樣的話後台goroutine可以在標準輸入被關閉後繼續打印reverb1服務器傳迴的數據要在reverb2服器也完成同的功能是比較睏難的;考**練習 8.4**。)
**练习 8.3** 在netcat3例子中conn然是一interface型的值,但是其底层真实类型是`*net.TCPConn`,代表一TCP接。一TCP接有读和写两个部分可以使用CloseRead和CloseWrite方法分别关闭它们。修改netcat3的主goroutine代码,只关闭网络链接中的部分,这样的话后台goroutine可以在标准输入被关闭后继续打印reverb1服务器传回的数据要在reverb2服器也完成同的功能是比较困难的;考**练习 8.4**。)