并發與并行的差別:
差別:
1. 并發:☞邏輯上具備同時處理多個任務的能力,指的是多個任務在同一時間段執行而不是同一時刻
2. 并行:☞實體上同一時刻執行多個任務
goroutine:
goroutine像一個多線程和協程的綜合體,運作時會建立多個限制來執行并發任務,且任務單元可排程到其他線程并行執行,最大限度提升執行效率。
go關鍵字
go println("hello world")
go funct(s){
println(s)
}("hello world")
建立并發任務通過go關鍵字就可,但是關鍵字go并非執行并發操作,而是建立一個并發任務單元,放置于系統隊列中等待排程器排程執行。等待執行過程中,目前流程不會阻塞,也不會等待該任務啟動,存在多個任務時也不會去保證并發任務的執行次序。
每個任務單元相比系統線程棧的MB級别來說小了很多,goroutine定義棧初始隻需要2KB。自定義棧采用按需配置設定的政策,在需要時進行擴容,最大能達到GB規模。
go關鍵字與defer一樣,會因為”延遲執行“而立即計算并複制執行參數,可參考下面例子:
package main
import "time"
var c int
func counter() int {
c++
return c
}
func main() {
a :=
go func(x, y int) {
time.Sleep(time.Second)
println("go:", x, y)
}(a, counter())
a +=
println("main:", a, counter())
time.Sleep(time.Second *)
}
//輸出結果:
main:
go:
通道
Go内置CSP模型,且鼓勵使用CSP通道,以通信來代替記憶體共享,實作并發安全,不需要開發人員自行維護資料一緻和完整性。
channel是顯式的,收發雙方必須都知道資料類型和具體通道。
channel從底層實作上來說是一個隊列,同步模式下收發雙方必須配對,然後直接複制資料給對方,配對失敗則置入等待隊列,直到出現适配的另一方
異步模式搶奪的是資料緩沖槽,發送方要求有空草可供寫入,接收方要求有緩沖資料可讀。
通道除了傳遞資料之外,通常也被用作事件通知。
func main(){
done := make(chan struct{}) //結束事件
c := make(chan string) //資料傳輸通道
go func(){
s:=<-c //接受資料
println(s)
close(done) //關閉通道,作為結束事件通知
}()
c <- "hi!" //發送資料
<-done //阻塞,置入等待 等待資料或事件通知
}
異步模式
可以使用len以及cap函數來擷取緩沖區的大小以及緩沖區已緩沖的數量
對于同步模式的channel使用len以及cap傳回結果均為0,此不同可用作區分channel是同步還是異步
import "unsafe"
func main(){
c := make(chan int) //建立一個帶3個緩沖槽的異步通道
c
c
println("通道中第一個值: ",<-c) //取出第一個資料
println("通道中第二個值: ",<-c) //取出第二個資料
println("通道中寫入值的數量: ",len(c))
println("通道的容積: ",cap(c))
println("通道變量的位址: ",c,"通道的長度: ",unsafe.Sizeof(c))
}
//輸出
//通道中第一個值: 1
//通道中第二個值: 2
//通道中寫入值的數量: 0
//通道的容積: 3
//通道變量的位址: 0xc42006a000 通道的長度: 8