Tôi đang thực hiện bài tập sử dụng kênh để triển khai hàng đợi. Cụ thể, tôi đang cố gắng sử dụng kích thước của một kênh để giới hạn số lượng goroutine đồng thời. Để wit, tôi đã viết đoạn mã sau:Cần trợ giúp để hiểu lý do tại sao chọn {} không chặn mãi mãi
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{}
}
Ngay bây giờ, các mã bị treo với:
throw: all goroutines are asleep - deadlock!
kỳ vọng của tôi là cuộc gọi đến chọn sẽ chặn vĩnh viễn và để cho các goroutines chấm dứt mà không có một bế tắc.
Vì vậy, tôi có một câu hỏi hai lần: tại sao không chọn chặn mãi mãi và, ngắn ném trong một thời gian.Sleep() gọi sau vòng lặp, làm thế nào tôi có thể tránh deadlocks?
Chúc mừng,
-mtw
Tôi sẽ cẩn thận với điều đó; tất cả mọi thứ trong đi được truyền theo giá trị. Bản đồ và lát thực sự được sao chép, tuy nhiên một phần dữ liệu được sao chép bao gồm các con trỏ đến dữ liệu cơ bản. http://golang.org/doc/faq#pass_by_value. Đó là một sự phân biệt tinh tế nhưng quan trọng; lát có các dữ liệu khác không phải là con trỏ và không được chia sẻ. – Greg
@Greg: "Bản đồ và lát thực sự được sao chép". Tách tóc, tôi nghĩ vậy. Theo tài liệu bạn đã liên kết: "Các giá trị bản đồ và slice hoạt động như con trỏ ... Sao chép một giá trị bản đồ hoặc lát không sao chép dữ liệu mà nó trỏ đến." Thuật ngữ của tôi không phải là bước với các tài liệu Go sử dụng bây giờ, nhưng ngữ nghĩa phần lớn là tương đương. – Ashe
@Greg: đã dọn dẹp văn xuôi ở đó một chút. – Ashe