Jak działają goroutines? (lub: goroutines i OS threads relation)
W Jaki Sposób inne goroutines mogą nadal wykonywać podczas wywoływania syscall? (przy użyciu GOMAXPROCS=1)
O ile mi wiadomo, podczas wywoływania syscall wątek traci kontrolę, dopóki syscall nie powróci.
Jak Go osiągnąć tę współbieżność bez tworzenia wątku systemowego na blocking-on - syscall goroutine?
Z dokumentacji:
Goroutines
Nazywają się goroutines, ponieważ istniejące terminy-threads, koroutiny, procesy i tak on-przekazać niedokładne konotacje. A goroutine ma prosty model: jest to funkcja wykonująca jednocześnie z innymi goroutinami w tej samej przestrzeni adresowej. Jest lekki, kosztuje niewiele więcej niż alokacja przestrzeni stosu. I stosy zacząć od małych, więc są tanie i rosną poprzez przydzielanie (i uwalnianie) przechowywanie sterty w razie potrzeby.
Goroutiny są multipleksowane na wiele wątków OS więc jeśli ktoś powinien blokuj, np. czekając na wejście / wyjście, inne nadal działają. Ich design skrywa wiele złożoności tworzenia wątków i zarządzanie.
4 answers
Jeśli goroutine blokuje, runtime uruchomi nowy wątek OS, aby obsłużyć inne goroutine, dopóki blokujący nie przestanie blokować.
Odniesienie: https://groups.google.com/forum/#! topic / golang-nuts / 2IdA34yR8gQ
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-06 19:57:58
Ok, więc oto czego się nauczyłem: Kiedy robisz surowe syscalls, go indeed tworzy wątek na blokowanie goroutine. Na przykład rozważ następujący kod:
package main
import (
"fmt"
"syscall"
)
func block(c chan bool) {
fmt.Println("block() enter")
buf := make([]byte, 1024)
_, _ = syscall.Read(0, buf) // block on doing an unbuffered read on STDIN
fmt.Println("block() exit")
c <- true // main() we're done
}
func main() {
c := make(chan bool)
for i := 0; i < 1000; i++ {
go block(c)
}
for i := 0; i < 1000; i++ {
_ = <-c
}
}
Ubuntu 12.04 zgłosiło 1004 wątków dla tego procesu.
Z drugiej strony, podczas korzystania z serwera HTTP Go i otwierania 1000 gniazd do niego, utworzono tylko 4 wątki systemu operacyjnego:
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Więc jest to mieszanka IOLoop i wątku na blokujące wywołanie systemowe.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-06 21:23:31
Nie może. jest tylko 1 goroutine, który może być uruchomiony w czasie, gdy GOMAXPROCS=1, Czy ten goroutine wykonuje wywołanie systemowe, czy coś innego.
Jednak większość blokujących wywołań systemowych, takich jak gniazda I/O, czekających na timer, nie jest blokowana w wywołaniu systemowym, gdy jest wykonywana z Go. Są one multipleksowane przez runtime Go na epoll, kqueue lub podobne udogodnienia, które System operacyjny zapewnia do multipleksowania I / o.
Dla innych rodzajów blokowania wywołań systemowych, które nie mogą być w przypadku Go 1.1 nie jest to jednak możliwe, ponieważ w przypadku Go 1.1 nie jest to możliwe, ponieważ nie jest to możliwe, ponieważ nie jest to możliwe, ponieważ w przypadku Go 1.1 nie jest to możliwe.]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 12:26:57
Musisz odróżnić numer procesora OD NUMERU wątku: możesz mieć więcej wątków niż fizyczne procesory, więc proces wielowątkowy może nadal wykonywać na pojedynczym procesorze.
Jak wyjaśnia przytoczona dokumentacja, goroutine nie jest wątkiem: jest tylko funkcją wykonywaną w wątku, który jest poświęcony kawałkowi przestrzeni stosu. Jeśli twój proces ma więcej niż jeden wątek, ta funkcja może być wykonywana przez każdy wątek. Więc goroutine, który blokuje z jakiegoś powodu lub inny (syscall, I/O, synchronizacja) może być wpuszczony do jego wątku, podczas gdy inne procedury mogą być wykonywane przez inny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-06 20:00:53