一道常常考的面試題

前段時間在找工做,也遇到一些不錯的面試題,其中有一道很常見,記錄一下,裏面還有一點搞不明白的:面試

下面兩段程序的輸出是什麼?spa

第一段:code

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            fmt.Println(i)
            wg.Done()
        }()
    }
    wg.Wait()
}

第二段:blog

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(n int) {
            fmt.Println(n)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

不少面試題解析裏面說第一段的10個goroutine輸出所有是10,我對這個結論是一直持懷疑態度的,由於輸出什麼,取決於那個goroutine裏面代碼被執行時外層i循環到哪裏,經我實測,也符合我本身的想法。隊列

clipboard.png

可是那天那個面試官很確定的說會所有輸出同樣的數,我忘記問他的理由是什麼了。ip

關於第二段程序,亂序輸出0-9,相信你們是沒有異議的。總計有10^10種可能。針對第二段程序,那位面試官接着問了一個我以爲挺有水平的問題:這10^10種輸出裏面,確定有一種是按順序0-9依次輸出的,能不能經過一些方法,讓這段程序的輸出順序固定下來?這個問題我一時還真的抓不到要點了。。。後來在面試官不斷的提點下,我纔想到面試官的考點,不由以爲這個面試官仍是頗有水平的。
第二段程序如何改動才能達到定序輸出的效果呢?咱們知道每一個goroutine生成後,在P的本地G隊列未滿的時候,是依次加入到P的本地G隊列裏的,若是隻有一個P可用,也就只有一個本地G隊列存在,那麼這些G的執行順序實際上是取決於P的G隊列的順序的,那麼答案也就出來了,咱們只要設置P的數量爲1,便可達到定序輸出的目的:it

func main() {
    runtime.GOMAXPROCS(1)
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(n int) {
            fmt.Println(n)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

clipboard.png
不過這裏我仍是有一點不明白的是,9爲何是第一個被輸出的?我猜大概是跟GMP調度有關的。目前還不明白,有知道的同窗能夠指點我一下,謝謝。class

以上若有錯誤,歡迎指出。cli

相關文章
相關標籤/搜索