goroutine的一個常見問題

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

轉自:http://blog.dccmx.com/2012/03/small-problem-about-goroutine/

goroutine是Go語言的標誌性特性之一。配合channel,形成了Go語言處理並發的基礎。但是,目前還有些小問題,或者說小不爽。就是會給你造成真並行的假象。

看下面的例子:

package main import (  "time"  "runtime") func main () {  ch := make(chan int)   go func(ch chan int) {    time.Sleep(1 * 1e9)    ch <- 1  }(ch)   go func(ch chan int) {    for {      select {      case <-ch:        println("got!!!")        return      default:        println("waiting...")      }    }  }(ch)   time.Sleep(2 * 1e9)}

這裡,我們的意圖很明顯,用一個goroutine做定時器,時間到了向channel發一訊號,再用一個goroutine做事,收到訊號後停止,最後一行sleep是為了防止main函數退出導致其他goroutine退出(為了省代碼,這裡不用channel同步了)。看起來天衣無縫,很是完美,驚歎一下Go的簡潔優美。但是,運行之後會發現,一直輸出waiting…,永遠不會退出!

為什嗎??

因為Go語言現在的實現還不是很成熟,預設情況下,同時只有1個goroutine在跑,而當這個goroutine阻塞的時候,才會調度到其他的goroutine去,就像協程,不過這裡由Go語言運行時幫你調度。

這個例子有三個解決方案。

1.在main函數裡面第一行調用runtime.GOMAXPROCS(2)函數,將同時goroutine數設為2(或者更大),這個解決方案至少在我的雙核機上跑是沒問題的。1秒後就輸出got!!!然後結束了。

2.製造阻塞,比如在println(“waiting…”)後面調用time.Sleep(1 * 1e8),這樣輸出10個waiting…後就got了。

3.手動切換,在println(“waiting…”)後面調用runtime.Gosched(),手動切換goroutine,這樣也能結束。

這個問題很典型,初學者經常會中招,雖然從語義上講,原始的做法並沒有錯,但是由於Go運行時還不夠成熟(至少Go1看來是不打算解決了,以後會取消GOMAXPROCS改為自動判斷),總之,大家小心點就好。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.