對Go語言瞭解前,咱們先來補一些基本概念shell
併發程序多線程
一個併發程序能夠在一個處理器或者內核上使用多個線程來執行任務,可是隻有同一個程序在某個時間點同時運行在多核或者多處理器上纔是真正的並行。併發
併發程序能夠是並行的,也能夠不是。操作系統
多線程缺點線程
使用多線程的應用難以作到準確,最主要的問題是內存中的數據共享,它們會被多線程以沒法預知的方式進行操做,致使一些沒法重現或者隨機的結果。設計
使用多線程須要在乎同步問題,可能出現死鎖,線程上下文切換帶來的開銷code
單線程中大計算量問題協程
利用多核CPU,將計算分發到各個子進程,將大量的計算分解掉,而後再經過進程間的事件消息來傳遞結果。接口
goroutines(協程)隊列
1.協程與線程關係
在協程和操做系統線程之間並沒有一對一的關係:協程是根據一個或多個線程的可用性,映 射(多路複用,執行於)在他們之上的;協程調度器在 Go 運行時很好的完成了這個工做。
2.協程實現
當系統調用(好比等待 I/O)阻塞協程時,其餘協程會繼續在其餘線程上工做。**協程 的設計隱藏了許多線程建立和管理方面的複雜工做。**
3.協程代價
協程是輕量的,比線程更輕。它們痕跡很是不明顯(使用少許的內存和資源):使用 4K 的棧內存就能夠在堆中建立它們。由於建立很是廉價,必要的時候能夠輕鬆建立並運行大 量的協程(在同一個地址空間中 100,000 個連續的協程)。
通道只能傳輸一種類型的數據,好比 chan int 或者 chan string,全部的類型均可以用於通道,空接口 interface{} 也能夠。甚至能夠(有時很是有用)建立通道的通道。
通道其實是類型化消息的隊列:使數據得以傳輸。它是先進先出(FIFO)結構的因此能夠保證發送給他們的元素的順序(有些人知道,通道能夠比做 Unix shells 中的雙向管道(tw-way pipe))。
默認狀況下,通訊是同步且無緩衝的:在有接受者接收數據以前,發送不會結束。能夠想象一個無緩衝的通道在沒有空間來保存數據的時候:必需要一個接收者準備好接收通道的數據而後發送者能夠直接把數據發送給接收者。因此通道的發送/接收操做在對方準備好以前是阻塞的。
例子:
package main import ( "fmt" "time" ) func main() { ch := make(chan string) go sendData(ch) go getData(ch) time.Sleep(1e9) } func sendData(ch chan string) { ch <- "Washington" ch <- "Tripoli" ch <- "London" ch <- "Beijing" ch <- "Tokio" } func getData(ch chan string) { var input string // time.Sleep(1e9) for { input = <-ch fmt.Printf("%s ", input) } }
輸出:
Washington Tripoli London Beijing Tokio