Jako głupie podstawowe ćwiczenie gwintowania, próbowałem wdrożyć sleeping barber problem w języku golang. Z kanałami to powinno być całkiem łatwe, ale wpadłem na heisenbug. To znaczy, kiedy próbuję ją zdiagnozować, problem znika!Drukowanie na standardowe wyjście powoduje zablokowanie goroutiny?
Należy rozważyć następujące kwestie. Funkcja main()
przesyła liczby całkowite (lub "klienci") na kanał shop
. barber()
czyta kanał shop
, aby wyciąć włosy "klientów". Jeśli wstawię instrukcję fmt.Print
do funkcji customer()
, program działa zgodnie z oczekiwaniami. W przeciwnym razie, barber()
nigdy nie obcina niczyich włosów.
package main
import "fmt"
func customer(id int, shop chan<- int) {
// Enter shop if seats available, otherwise leave
// fmt.Println("Uncomment this line and the program works")
if len(shop) < cap(shop) {
shop <- id
}
}
func barber(shop <-chan int) {
// Cut hair of anyone who enters the shop
for {
fmt.Println("Barber cuts hair of customer", <-shop)
}
}
func main() {
shop := make(chan int, 5) // five seats available
go barber(shop)
for i := 0; ; i++ {
customer(i, shop)
}
}
Każdy pomysł, co się dzieje?
Twoja odpowiedź ma zastosowanie, jeśli w runtime go używany jest tylko jeden wątek. Ustawienie GOMAXPROCS poprzez wywołanie runtime podobnie jak lazy1 mówi, lub ustawienie zmiennej środowiskowej pozwoli także uruchomić goroutine równolegle do innych goroutines w osobnym wątku. Być może warto rozszerzyć swoją odpowiedź, aby odzwierciedlić, w jaki sposób jego środowisko wykonawcze multipleksuje goroutiny w dostępnych wątkach. –