[英]How do goroutines work? (or: goroutines and OS threads relation)
[英]How do goroutines work?
我正在關注Go Tour ,當涉及到goroutines時我有點卡住了。 我知道他們非常輕量級,每次goroutine阻止,另一個將開始,但我無法理解這個例子實際上是如何工作的:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
據我所知,一個goroutine是針對具有參數“world”的say函數啟動的,但據我所知,應該打印“world”五次並且“hello”一次。 但是我不明白為什么輸出是這樣的:
hello
world
hello
world
hello
world
hello
world
hello
從我對其他語言的線程的有限理解,輸出應該是這樣的:
hello
world
world
world
world
world
或者像這樣:
world
world
world
hello
world
world
為什么第二行也執行五次? go
語句下面的任何內容都go
歸類為go例程的一部分嗎?
下一張幻燈片還顯示了我無法再次回頭看的內容:
package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
對於切片的后半部分開始goroutine,然后為切片的第一部分開始另一個goroutine,但是值x
和y
已經被分配了兩個不同的值。 我看到它的方式sum
函數將它的總和發送到通道c
,然后下一個sum
將它的總和發送到相同的通道c
那么如何為這兩個變量分配兩個不同的值? 通道c
不應該有一個單一的sum
值嗎?
我很欣賞這是一個很長的問題,但我無法找到這些問題的答案。
為什么第二行也執行5次?
第二行將在main()
線程中每隔5次打印hello
。
但同時第一行go say("world")
也將在一個單獨的goroutine中每秒打印五次世界。
Sleep
確保每個例程產生,允許另一個例程恢復。
因此輸出:
hello
world
hello
world
hello
world
hello
world
hello
我看到它的方式sum函數將它的總和發送到通道c,然后下一個和將它的總和發送到相同的通道c,那么如何為這兩個變量分配兩個不同的值?
因為每個發送都將在c
阻塞,直到讀取通道c
。
由於有兩個寫入c
,您需要閱讀:
x, y := <-c, <-c // receive from c twice.
Golang Spec的Assignement部分允許在以下情況下進行元組賦值:
左邊的操作數數量必須等於右邊的表達式數量,每個表達式必須是單值,右邊的
nth
表達式分配給左邊的第n個操作數。
對於第一個函數,您應該看到VonC所呈現的值。 hello
打印5次的原因是因為函數say
打印東西5次。 想象一下沒有goroutine的程序。 我認為這並不能保證你會得到hello
, world
完美穿插,但我可能錯了。
頻道工作的原因是:
empty out
通道,即當你將c
分配給x
它會移除傳遞給通道的第一個總和,當它將c
分配給y
它傳遞給第二個值(再次我認為順序不是保證,因為x
可以具有第一半部和y
下半年總和或反之亦然。 如果你把頻道想象成一種隊列我覺得它更有意義。 求和goroutines將值推送到隊列,並且賦值按順序彈出值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.