我正在使用通道來實現隊列的練習。具體來說,我試圖使用通道的大小來限制同步goroutines的數量。要曉得,我寫了下面的代碼:需要幫助瞭解選擇{}不會永久阻止的原因
package main
import "fmt"
import "time"
import "math/rand"
func runTask (t string, ch *chan bool) {
start := time.Now()
fmt.Println("starting task", t)
time.Sleep(time.Millisecond * time.Duration(rand.Int31n(1500))) // fake processing time
fmt.Println("done running task", t, "in", time.Since(start))
<- *ch
}
func main() {
numWorkers := 3
files := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
activeWorkers := make(chan bool, numWorkers)
for _, f := range files {
activeWorkers <- true
fmt.Printf("activeWorkers is %d long.\n", len(activeWorkers))
go runTask(f, &activeWorkers)
}
select{}
}
眼下,代碼崩潰與:
throw: all goroutines are asleep - deadlock!
我的期望是,調用選擇將永遠阻止並讓夠程終止無僵局。
所以我有一個雙重的問題:爲什麼不選擇永遠阻塞,並在短時間內投入。調用for循環後,如何避免死鎖?
乾杯,
-mtw
我會小心的;一切都以價值傳遞。地圖和切片確實被複制,但是複製數據的一部分包含指向底層數據的指針。 http://golang.org/doc/faq#pass_by_value。這是一個微妙而重要的區別;切片具有不是指針的其他數據,也不共享。 – Greg 2014-06-10 04:24:02
@Greg:「地圖和切片確實被複制」。我想,分裂頭髮。根據您鏈接的文檔:「地圖和切片值的行爲與指針類似......複製地圖或切片值不會複製它指向的數據。」我的術語與Go文檔現在使用的不一致,但語義在很大程度上是等價的。 – Ashe 2014-06-10 04:46:16
@Greg:已經把那裏的散文清理了一下。 – Ashe 2014-06-10 04:49:02