(1)理解go func背後發生了什麼?

參考:https://studygolang.com/articles/21588?fr=sidebar

先看下下面這段代碼?

(1)A與B分佈在不同的goroutine隊列

package main

import (
	"fmt"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(20)
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Println("A: ", i)
			wg.Done()
		}()
	}
	for i := 0; i < 10; i++ {
		go func(i int) {
			fmt.Println("B: ", i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

輸出:

A:  4
B:  4
B:  0
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
B:  9
A:  10
B:  7
A:  10
B:  2
B:  5
B:  3
A:  8
B:  6
B:  1
B:  8

結論:
A與B所在的協程執行順序不確定,A輸出的大部分爲10,可能輸出i的中間值
B輸出的是0到9的值,輸出順序也是不確定的。
這是因爲A與B分佈在不同的goroutine隊列。

再試下面的代碼

package main

import (
	"fmt"
	"sync"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(1) //設置協程調度只有一個P
    wg := sync.WaitGroup{}
    wg.Add(20)
    for i := 0; i < 10; i++ {
        go func() {
            fmt.Println("A: ", i)
            wg.Done()
        }()
    }
    for i := 0; i < 10; i++ {
        go func(i int) {
            fmt.Println("B: ", i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

輸出:

B:  9
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
A:  10
B:  0
B:  1
B:  2
B:  3
B:  4
B:  5
B:  6
B:  7
B:  8

結論:
多次運行結果都是上面一樣。先輸出B: 9,然後10個A: 10,然後B輸出0到8
runtime. GOMAXPROCS(1) 強行指定了只創建一個 “P” 來處理併發,這使得例子中的 20 個 goroutine 會是串行的

編譯器會把 go 後面跟着的函數與參數都打包成g對象,等待系統調度。

再試下面代碼

package main

import (
	"runtime"
	"time"
)

func main() {
	runtime.GOMAXPROCS(1)
	for i := 0; i < 10; i++ {
		go print(i)
	}
	time.Sleep(time.Second)
}

輸出結果:0 1 2 3 ... 8 9 注意輸出的不是10個10
再如下:

package main

import (
	"runtime"
	"time"
)

func main() {
	runtime.GOMAXPROCS(1)
	for i := 0; i < 10; i++ {
		go println(i)
	}
	runtime.Gosched()
	time.Sleep(time.Second)
}

輸出結果:

9
0
1
2
3
4
5
6
7
8

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章