기본적으로 순서대로 트리를 가로 지르는 Walk function in the go tutorial을 쓰고 있습니다. 나는이 작품이 무엇 :왜 새 서브 루틴으로 Walk를 실행해야합니까?
package main
import (
"fmt"
"code.google.com/p/go-tour/tree"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk__helper(t *tree.Tree, ch chan int) {
if (t == nil) {
return
}
Walk__helper(t.Left, ch)
ch <- t.Value
Walk__helper(t.Right, ch)
}
func Walk(t *tree.Tree, ch chan int) {
Walk__helper(t, ch)
close(ch)
}
func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for v := range ch {
fmt.Println(v)
}
}
왜 내가 대신 Walk(tree.New(1), ch)
의 go Walk(tree.New(1), ch)
을 사용해야합니다?
나는 go
키워드가 기본적으로 새 스레드를 생성한다는 인상하에있었습니다. 이 경우 서브 루틴이 완료되기 전에 for 루프가 실행될 수 있으므로 문제가 발생합니다.
이상하게도 go
키워드를 가져 오면 교착 상태가됩니다. 이것은 오히려 나에게 반 직관적이다. go
여기 정확히 키워드는 무엇입니까?
아, 감사합니다. 스레드가 goroutine과 어떻게 다른지에 관해서는, 동기화 (뮤텍스, 세마포어)가 기본적으로 채널 버퍼로 구현된다는 것을 의미한다고 생각하십니까? –
그들은 완전히 다릅니다. Goroutines는 스레드 위에있는 추상화입니다. Go 실행 시간은 운영 체제가 Threads ..와 같이 goroutines를 분할하지만 그렇게하는 것이 훨씬 저렴합니다. 단일 스레드에서 여러 goroutine을 시간 조각 할 수 있습니다. goroutine이 스레드를 차단하려고 선취 될 수있는 경우 런타임은 새로운 스레드를 생성하고 다른 스레드가 차단되는 동안 goroutine을 가로 질러 시간 슬라이스합니다. 그것은 그것의 _basic_ 개요입니다 .. 거기에 너무 많은 것이 있습니다. –
낮은 레벨에서 OS 스레드와 몇 가지 중요한 차이점이 있습니다. goroutines는 나중에 확장 될 수있는 작은 스택으로 시작하므로 하나를 시작하는 데 많은 시간이나 RAM이 필요하지 않습니다. Go의'net' 패키지, 채널 등은 특정 차단 작업이 발생할 때 goroutine을 Go의 사용자 모드 스케줄러로 만듭니다. 에 넘겨지면 사용자 모드 스케줄러는 커널 공간을 통해 값 비싼 여행을하지 않고도 다른 goroutine으로 제어를 전달할 수 있습니다. 어떤 점에서 그들은 Windows 세계가 "섬유"라고 부르는 것과 같습니다. – twotwotwo