久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網
      最全最豐富的資訊網站

      golang并發(fā)不是并行

      golang并發(fā)不是并行

      并發(fā)不等于并行

      golang的核心開發(fā)人員Rob Pike專門提到了這個話題 (推薦學習:go)

      雖然我們在for循環(huán)中使用了go 創(chuàng)建了一個goroutine,我們想當然會認為,每次循環(huán)變量時,golang一定會執(zhí)行這個goroutine,然后輸出當時的變量。

      這時,我們就陷入了思維定勢。 默認并發(fā)等于并行。

      誠然,通過go創(chuàng)建的goroutine是會并發(fā)的執(zhí)行其中的函數(shù)代碼。

      但一定會按照我們所設想的那樣每次循環(huán)時執(zhí)行嗎?

      答案是否定的!

      Rob Pike專門提到了golang中并發(fā)指的是代碼結構中的某些函數(shù)邏輯上可以同時運行,但物理上未必會同時運行。而并行則指的就是在物理層面也就是使用了不同CPU在執(zhí)行不同或者相同的任務。

      golang的goroutine調度模型決定了,每個goroutine是運行在虛擬CPU中的(也就是我們通過runtime.GOMAXPROCS(1)所設定的虛擬CPU個數(shù))。

      虛擬CPU個數(shù)未必會和實際CPU個數(shù)相吻合。每個goroutine都會被一個特定的P(虛擬CPU)選定維護,而M(物理計算資源)每次回挑選一個有效P,然后執(zhí)行P中的goroutine。

      每個P會將自己所維護的goroutine放到一個G隊列中,其中就包括了goroutine堆棧信息,是否可執(zhí)行信息等等。默認情況下,P的數(shù)量與實際物理CPU的數(shù)量相等。

      因此當我們通過循環(huán)來創(chuàng)建goroutine時,每個goroutine會被分配到不同的P隊列中。而M的數(shù)量又不是唯一的,當M隨機挑選P時,也就等同隨機挑選了goroutine。

      在本題中,我們設定了P=1。所以所有的goroutine會被綁定到同一個P中。 如果我們修改runtime.GOMAXPROCS的值,就會看到另外的順序。 如果我們輸出goroutine id,就可以看到隨機挑選的效果:

      func main() { wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { var buf [64]byte n := runtime.Stack(buf[:], false) idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0] id, err := strconv.Atoi(idField) if err != nil { panic(fmt.Sprintf("cannot get goroutine id: %v", err)) } fmt.Println("go routine 1 i: ", i, id) wg.Done() }() } for i := 0; i < 10; i++ { go func(i int) { var buf [64]byte n := runtime.Stack(buf[:], false) idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0] id, err := strconv.Atoi(idField) if err != nil { panic(fmt.Sprintf("cannot get goroutine id: %v", err)) } fmt.Println("go routine 2 i: ", i, id) wg.Done() }(i)  } wg.Wait() }

      輸出如下:

      go routine 2 i: 9 24 go routine 1 i: 10 11 go routine 1 i: 10 5 go routine 1 i: 10 6 go routine 2 i: 3 18 go routine 1 i: 10 9 go routine 1 i: 10 10 go routine 1 i: 10 8 go routine 2 i: 0 15 go routine 2 i: 4 19 go routine 2 i: 6 21 go routine 1 i: 10 7 go routine 1 i: 10 14 go routine 2 i: 7 22 go routine 2 i: 8 23 go routine 1 i: 10 13 go routine 2 i: 5 20 go routine 1 i: 10 12 go routine 2 i: 1 16 go routine 2 i: 2 17 ?> ~/S/g/g/s/t/C/goroutine ./goroutine go routine 1 i: 10 11 go routine 2 i: 9 24 go routine 1 i: 10 6 go routine 1 i: 10 14 go routine 1 i: 10 9 go routine 1 i: 10 10 go routine 1 i: 10 12 go routine 2 i: 0 15 go routine 1 i: 10 13 go routine 1 i: 10 5 go routine 2 i: 1 16 go routine 2 i: 5 20 go routine 1 i: 10 7 go routine 2 i: 7 22 go routine 2 i: 3 18 go routine 2 i: 2 17 go routine 2 i: 4 19 go routine 1 i: 10 8 go routine 2 i: 8 23 go routine 2 i: 6 21

      我們再回到這道題中,雖然在循環(huán)中通過go定義了一個goroutine。但我們說到了,并發(fā)不等于并行。因此雖然定義了,但此刻不見得就會去執(zhí)行。

      需要等待M選擇P之后,才能去執(zhí)行goroutine。 關于golang中goroutine是如何進行調度的(GPM模型),可以參考Scalable Go Scheduler Design Doc或者LearnConcurrency

      贊(0)
      分享到: 更多 (0)
      網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號