回到简体

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.9. 併發的退出
## 8.9. 并发的退出
候我需要通知goroutine停止它正在的事情,比如一正在執行計算的web服,然而它的客端已經斷開了和服端的接。
候我需要通知goroutine停止它正在的事情,比如一正在执行计算的web服,然而它的客端已经断开了和服端的接。
Go語言併沒有提供在一goroutine中止另一goroutine的方法於這樣會導致goroutine之的共享量落在未定義的狀態上。在8.7中的rocket launch程序中往名字叫abort的channel里送了一個簡單的值在countdown的goroutine中會把這個值理解自己的退出信。但是如果我想要退出兩個或者任意多goroutine怎麽辦呢?
Go语言并没有提供在一goroutine中止另一goroutine的方法于这样会导致goroutine之的共享量落在未定义的状态上。在8.7中的rocket launch程序中往名字叫abort的channel里送了一个简单的值在countdown的goroutine中会把这个值理解自己的退出信。但是如果我想要退出两个或者任意多goroutine怎么办呢?
可能的手段是向abort的channel里送和goroutine目一多的事件退出它。如果些goroutine中已有一些自己退出了,那麽會導致我的channel里的事件比goroutine多,這樣導致我們的發送直接被阻塞。另一方面,如果些goroutine又生成了其它的goroutine的channel里的目又太少了所以有些goroutine可能會無法接收到退出消息。一般情下我是很知道在某一個時刻具有多少goroutine在行着的。另外,當一個goroutineabort channel中接收到一值的候,他會消費掉這個值,這樣其它的goroutine就法看到這條信息。了能夠達到我退出goroutine的目的需要更靠的策略,來通過一個channel把消息播出去,這樣goroutine們能夠看到這條事件消息,且在事件完成之,可以知道件事已經發生過了。
可能的手段是向abort的channel里送和goroutine目一多的事件退出它。如果些goroutine中已有一些自己退出了,那么会导致我的channel里的事件比goroutine多,这样导致我们的发送直接被阻塞。另一方面,如果些goroutine又生成了其它的goroutine的channel里的目又太少了所以有些goroutine可能会无法接收到退出消息。一般情下我是很知道在某一个时刻具有多少goroutine在行着的。另外,当一个goroutineabort channel中接收到一值的候,他会消费掉这个值,这样其它的goroutine就法看到这条信息。了能够达到我退出goroutine的目的需要更靠的策略,来通过一个channel把消息广播出去,这样goroutine们能够看到这条事件消息,且在事件完成之,可以知道件事已经发生过了。
迴憶一下我們關閉了一channel且被消掉了所有已送的值操作channel之的代可以立卽被執行,併且會産生零值。我可以將這個機製擴展一下,來作爲我們的廣播機製不要向channel送值,而是用關閉一個channel來進行廣播。
回忆一下我们关闭了一channel且被消掉了所有已送的值操作channel之的代可以立即被执行,并且会产生零值。我可以将这个机制扩展一下,来作为我们的广播机制不要向channel送值,而是用关闭一个channel来进行广播。
要一些小改,我就可以把退出邏輯加入到前一的du程序。首先們創建一退出的channel這個channel不向其中送任何值,但其所在的閉包內要寫明程序需要退出。我們同時還定義了一工具函cancelled這個函數在被調用的時候會輪詢退出狀態
要一些小改,我就可以把退出逻辑加入到前一的du程序。首先们创建一退出的channel这个channel不向其中送任何值,但其所在的闭包内要写明程序需要退出。我们同时还定义了一工具函cancelled这个函数在被用的时候会轮询退出状态
<u><i>gopl.io/ch8/du4</i></u>
```go
@@ -24,7 +24,7 @@ func cancelled() bool {
}
```
下面我們創建一個從標準輸入流中讀取內容的goroutine是一個比較典型的接到端的程序。每當有輸入被到(比如用按了迴車鍵),這個goroutine就把取消消息通過關閉done的channel播出去。
下面我们创建一个从标准输入流中读取内容的goroutine是一个比较典型的接到端的程序。每当有输入被到(比如用按了回车键),这个goroutine就把取消消息通过关闭done的channel广播出去。
```go
// Cancel traversal when input is detected.
@@ -34,7 +34,7 @@ go func() {
}()
```
在我需要使我的goroutine來對取消進行響應。在main goroutine中添加了select的第三case句,嚐試從done channel中接收容。如果這個case被滿足的在select到的時候卽會返迴,但在束之前我需要把fileSizes channel中的容“排”空在channel被關閉之前,舍掉所有值。這樣可以保證對walkDir的調用不要被向fileSizes送信息阻塞住,可以正地完成。
在我需要使我的goroutine来对取消进行响应。在main goroutine中添加了select的第三case句,尝试从done channel中接收容。如果这个case被足的在select到的时候即会返回,但在束之前我需要把fileSizes channel中的容“排”空在channel被关闭之前,舍掉所有值。这样可以保证对walkDir的用不要被向fileSizes送信息阻塞住,可以正地完成。
```go
for {
@@ -51,7 +51,7 @@ for {
}
```
walkDir這個goroutine一啟動就會輪詢取消狀態,如果取消狀態被設置的話會直接返迴,併且不做外的事情。這樣我們將所有在取消事件之後創建的goroutine改變爲無操作。
walkDir这个goroutine一启动就会轮询取消状态,如果取消状态被设置的话会直接返回,并且不做外的事情。这样我们将所有在取消事件之后创建的goroutine改变为无操作。
```go
func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) {
@@ -65,9 +65,9 @@ func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) {
}
```
在walkDir函的循中我們對取消狀態進行輪詢可以帶來明顯的益,可以避免在取消事件發生時還去創建goroutine。取消本身是有一些代的;想要快速的響應需要程序邏輯進行侵入式的改。保在取消生之不要有代太大的操作可能需要改你代里的很多地方,但是在一些重要的地方去檢査取消事件也確實能帶來很大的好
在walkDir函的循中我们对取消状态进行轮询可以带来明显的益,可以避免在取消事件发生时还去创建goroutine。取消本身是有一些代的;想要快速的响应需要程序逻辑进行侵入式的改。保在取消生之不要有代太大的操作可能需要改你代里的很多地方,但是在一些重要的地方去检查取消事件也确实能带来很大的好
對這個程序的一個簡單的性能分析可以揭示瓶在dirents函數中獲取一個信號量。下面的select可以讓這種操作可以被取消,且可以取消的延遲從幾百毫秒降低到十毫秒。
对这个程序的一个简单的性能分析可以揭示瓶在dirents函数中获取一个信号量。下面的select可以让这种操作可以被取消,且可以取消的延迟从几百毫秒降低到十毫秒。
```go
func dirents(dir string) []os.FileInfo {
@@ -81,8 +81,8 @@ func dirents(dir string) []os.FileInfo {
}
```
現在當取消發生時,所有台的goroutine都迅速停止且主函數會返迴。當然,主函數返迴時,一程序退出,而我們又無法在主函退出的時候確認其已經釋放了所有的源(譯註:因程序都退出了,你的代碼都沒法執行了)。里有一方便的竅門我們可以一用:取代掉直接主函數返迴,我們調用一panicruntime把每一goroutine的dump下。如果main goroutine是唯一一剩下的goroutine的,他清理掉自己的一切源。但是如果有其它的goroutine有退出,他可能沒辦法被正地取消掉,也有可能被取消但是取消操作很花時間;所以里的一個調研還是很有必要的。我用panic來獲取到足的信息來驗證我們上面的判,看看最到底是什麽樣的情
现在当取消发生时,所有台的goroutine都迅速停止且主函数会返回。当然,主函数返回时,一程序退出,而我们又无法在主函退出的时候确认其已经释放了所有的源(译注:因程序都退出了,你的代码都没法执行了)。里有一方便的窍门我们可以一用:取代掉直接主函数返回,我们调用一panicruntime把每一goroutine的dump下。如果main goroutine是唯一一剩下的goroutine的,他清理掉自己的一切源。但是如果有其它的goroutine有退出,他可能没办法被正地取消掉,也有可能被取消但是取消操作很花时间;所以里的一个调研还是很有必要的。我用panic来获取到足的信息来验证我们上面的判,看看最到底是什么样的情
**練習 8.10** HTTP求可能因http.Request結構體中Cancel channel的關閉而取消。改8.6中的web crawler支持取消http求。提示http.Get併沒有提供方便地定製一個請求的方法。你可以用http.NewRequest取而代之,置它的Cancel字段用http.DefaultClient.Do(req)來進行這個http求。)
**练习 8.10** HTTP求可能因http.Request结构体中Cancel channel的关闭而取消。改8.6中的web crawler支持取消http求。提示http.Get并没有提供方便地定制一个请求的方法。你可以用http.NewRequest取而代之,置它的Cancel字段用http.DefaultClient.Do(req)来进行这个http求。)
**練習 8.11** 接着8.4.4中的mirroredQuery流程實現一個併發請求url的fetch的變種。當第一個請求返迴時,直接取消其它的求。
**练习 8.11** 接着8.4.4中的mirroredQuery流程实现一个并发请求url的fetch的变种。当第一个请求返回时,直接取消其它的求。