Go語言基礎:並發

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

並行與並發

理論式的概念:

並行:多件事在同一時刻發生。
並發:多件事在同一時間間隔發生。

5歲小孩都能看懂的解釋:


摘自:http://www.cnblogs.com/yangecnu/p/3164167.html 和 Concurrent and Parallel Programming
上文如果用程式員的語言來講,CPU處理器相當於的咖啡機的角色,任務相當於隊列中的人。

並發與並行的區別:

一定要仔細閱讀此文:http://blog.csdn.net/coolmeme/article/details/9997609 。這篇文章提到了網路伺服器並發串連數、吐吞量、寬頻概念,對於初學者應該很受用。

Goruntine

goruntine原理

我們知道Go從語言層面就支援了並發,而goruntine是go並發設計的核心。goruntine說到底是協程【Go Web 編程裡是線程,也是對的,因為協程類似於使用者態線程】。具體原理實現參考:
1. 以goroutine為例看協程的相關概念
2. goroutine與調度器
3. 廖雪峰:協程
4. 知乎:協程的好處是什嗎?
5. 知乎:golang的goroutine是如何?的?
這些參考文章建議讀者好好看看。
瞭解了協程、goruntine的實現機制,接下來學習如何啟動goruntine。

啟動goruntine

goroutine 通過關鍵字 go 就啟動了一個 goroutine。

go hello(a, b, c)//普通函數前加go

例子:

package mainimport (    "fmt"    "runtime")func say(s string) {    for i := 0; i < 5; i++ {        runtime.Gosched() //表示讓cpu將控制權給其他人        fmt.Println(s)    }}func main() {    runtime.GOMAXPROCS(1)    go say("world")    say("hello")}

輸出:

helloworldhelloworldhelloworldhelloworldhello

很簡單,在函數前加一個go關鍵詞就啟動了goruntine。

Channel

channel是什麼

channel是一種通訊通道,goruntine之間的資料通訊通過channel來實現。goruntine通過channel發送或者接收訊息。

channel的基本操作文法:

cl := make(chan int) //建立一個無緩衝的int型channel,可以根據需求建立bool、string等類型的channelc1 := make(chan int, 4) //建立有緩衝的int型channelcl <- x //發送x到channel clx := <- cl //從cl中接收資料,並賦值給x

無緩衝的例子:

package mainimport (    "fmt"    "time")func sendChan(cl chan string) {    fmt.Println("[send_start]")    cl <- "hello world" // 向cl中加資料,如果沒有其他goroutine來取走這個資料,那麼掛起sendChan, 直到getChan函數把"hello world"這個資料拿走    fmt.Println("[send_end]")}func getChan(cl chan string) {    fmt.Println("[get_start]")    s := <-cl // 從cl取資料,如果cl中還沒放資料,那就掛起getChan線程,直到sendChan函數中放資料為止    fmt.Println("[get_end]" + s)}func main() {    cl := make(chan string)    go sendChan(cl)    go getChan(cl)    time.Sleep(time.Second)}

輸出:

[send_start][get_start][get_end]hello world[send_end]

上面的例子存在3個goruntine,注意main也在一個goruntine中。如果函數main中沒有 time.Sleep(time.Second),你會發現什麼輸出都不會有,為什麼呢?是因為另外兩個goruntine還沒來得及跑,主函數main就已經退出了。
所以需要讓main等一下,time.Sleep(time.Second)就是讓main停頓一秒再輸出。
無緩衝的channel的接收和發送都是阻塞的,也就是說:

  • 資料流入無緩衝通道, 如果沒有其他goroutine來拿走這個資料,那麼當前線阻塞
  • 從無緩衝通道取資料,必須要有資料流進來才可以,否則當前goroutine阻塞

有緩衝的例子:

package mainimport (    "fmt"    "time")func sendChan(cl chan int, len int) {    fmt.Println("sendChan_enter")    for i := 0; i < len; i++ {        fmt.Println("# ", i)        cl <- i //cl的儲存第4個資料的時候,會阻塞當前goruntine,直到其它goruntine取走一個或多個資料    }    fmt.Println("sendChan_end")}func getChan(cl chan int, len int) {    fmt.Println("getChan_enter")    for i := 0; i < len; i++ {        data := <-cl        fmt.Println("$ ", data)//當cl的資料為空白時,阻塞當前goruntine,直到新的資料寫入cl    }    fmt.Println("getChan_end")}func main() {    cl := make(chan int, 3)// 寫入3個元素都不會阻塞當前goroutine, 儲存個數達到4的時候會阻塞    go sendChan(cl, 10)    go getChan(cl, 5)     time.Sleep(time.Second)}

輸出:

sendChan_enter#  0#  1#  2#  3getChan_enter$  0$  1$  2$  3#  4#  5#  6#  7#  8$  4getChan_end

為什麼sendChan_end沒有輸出?
getChan取完5個資料後,getChan這個goruntine就會掛起,而sendChan線程因為資料填滿,無法將剩餘的資料寫入chanl而掛起,最後因main所在的goruntine逾時1秒結束而結束。故而看不到sendChan_end的輸出。

  • 有緩衝的channel是可以無阻塞的寫入,當緩衝填滿時,再次寫入新的資料時,當前goruntine會發生阻塞,直到其它goruntine從channel中取走一些資料:
  • 有緩衝的channel可以無阻塞的擷取資料,當資料取空時,再次取新的資料時,當前的goruntine會發生阻塞,直到其它goruntine往channel寫入新的資料

close

生產者【發送channel的goruntine】通過關鍵字 close 函數關閉 channel。關閉 channel 之後就無法再發送任何資料了, 在消費方【接收channel的goruntine】可以通過文法 v, ok := <-ch 測試 channel 是否被關閉。如果 ok 返回 false,那麼說明 channel 已經沒有任何資料並且已經被關閉。

不過一般用得少,網上關於它的描述也不多。

select

文法結構類似於switch。

select {    case cl<-x:        go語句    case <-cl:        go語句    default: //可選,        go語句}
  • 每個case只能是channel的擷取或者寫入,不能是其它語句。
  • 當每個case都無法執行,如果有default,執行default;如果沒有default,當前goruntine阻塞。
  • 當多個case都可以執行的時候,隨機選出一個執行。

關於select的用法,強烈推薦閱讀:【GOLANG】Go語言學習-select用法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.