Go 併發concurrency 學習筆記
- 很多人都是衝著 Go 大肆宣揚的高併發而忍不住躍躍欲試,但其實從原始碼的解析來看,goroutine 只是由官方實現的超級“執行緒池”而已。不過話說回來,每個例項 4-5KB 的棧記憶體佔用和由於實現機制而大幅減少的建立和銷燬開銷,是製造 Go 號稱的高併發的根本原因。另外,goroutine 的簡單易用,也在語言層面上給予了開發者巨大的便利。
- 併發不是並行:Concurrency Is Not Parallelism
- 併發主要由切換時間片來實現“同時”執行,在並行則是直接利用多核實現多執行緒的執行,但 Go 可以設定使用核數,以發揮多核計算機的能力。
- Goroutine 奉行通過通訊來共享記憶體,而不是共享記憶體來通訊。
Channel
- Channel 是 goroutine 溝通的橋樑,大都是阻塞同步的
- 通過 make 建立,close 關閉
- Channel 是引用型別
- 可以使用 for range 來迭代不斷操作 channel
- 可以設定單向或雙向通道
- 可以設定快取大小,在未被填滿前不會發生阻塞
通過channel計算10次,累加
方法一:
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("NumCPU:", runtime.NumCPU())
//獲取cpu核心數量
runtime.GOMAXPROCS(runtime.NumCPU())
// channel bool型別 快取長度為10
c := make(chan bool, 10)
for i := 0; i < 10; i++ {
go Go(c, i)
}
for i := 0; i < 10; i++ {
<-c
}
}
func Go(c chan bool, index int) {
a := 1
for i := 0; i < 100000000; i++ {
a += i
}
fmt.Println(index, a)
c <- true
}
輸出結果:
方法二:
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
wg := sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
go Go(&wg, i)
}
wg.Wait()
}
func Go(wg *sync.WaitGroup, index int) {
a := 1
for i := 0; i < 100000000; i++ {
a += i
}
fmt.Println(index, a)
wg.Done()
}
輸出結果:
Select
- 可處理一個或多個 channel 的傳送與接收
- 同時有多個可用的 channel時按隨機順序處理
- 可用空的 select 來阻塞 main 函式
- 可設定超時
1、處理多個 channel
package main
import (
"fmt"
)
func main() {
c1, c2 := make(chan int), make(chan string)
o := make(chan bool, 2)
go func() {
for {
select {
case v, ok := <-c1:
if !ok {
o <- true
break
}
fmt.Println("c1", v)
case v, ok := <-c2:
if !ok {
o <- true
break
}
fmt.Println("c2", v)
}
}
}()
c1 <- 1
c2 <- "hhhh"
c1 <- 9
c2 <- "uuuuu"
close(c1)
close(c2)
for i := 0; i < 2; i++ {
<-o
}
}
輸出結果:
2、同時有多個可用的 channel時按隨機順序處理
package main
import (
"fmt"
)
func main() {
o := make(chan int)
go func() {
for v := range o {
fmt.Println(v)
}
}()
for {
select {
case o <- 1:
case o <- 2:
}
}
}
輸出結果:
3、超時
package main
import (
"fmt"
"time"
)
func main() {
o := make(chan int)
select {
case v := <-o:
fmt.Println(v)
case <-time.After(3 * time.Second):
fmt.Println("TimeOut")
}
}
輸出結果:
本文參考整理自:《Go 程式設計基礎》
個人微信公眾號:
作者:jiankunking 出處:http://blog.csdn.net/jiankunking
相關文章
- Go基礎學習六之併發concurrencyGo
- 【Go學習筆記11】併發(一)Go筆記
- Go 筆記之併發Go筆記
- 《筆記》之學習高併發筆記
- JAVA 學習併發筆記(一)Java筆記
- (一)Java併發學習筆記Java筆記
- 學習 Go併發模型Go模型
- Go 學習筆記Go筆記
- go併發程式設計筆記Go程式設計筆記
- GO 方法學習筆記Go筆記
- go channel學習筆記Go筆記
- go defer 學習筆記Go筆記
- go 學習筆記---切片Go筆記
- Go 方法 學習筆記Go筆記
- Go 介面 學習筆記Go筆記
- Go 反射 學習筆記Go反射筆記
- 【學習筆記】Go Modules 使用筆記Go
- Go 進階學習筆記Go筆記
- go 閉包學習筆記Go筆記
- go 學習筆記---map(字典)Go筆記
- 【Go學習筆記4】切片Go筆記
- Go 函式 學習筆記Go函式筆記
- Go 結構 學習筆記Go筆記
- go學習筆記——gin框架Go筆記框架
- go 學習筆記之初識 go 語言Go筆記
- LevelDB 學習筆記2:合併筆記
- Java併發程式設計實踐(Java concurrency in practice)線上示例學習Java程式設計
- Go 入門指南學習筆記Go筆記
- GO 學習筆記->結構體Go筆記結構體
- go-ethereum學習筆記(一)Go筆記
- Go學習筆記-GMP詳解Go筆記
- Go學習筆記-Zap日誌Go筆記
- Go型別特性-學習筆記Go型別筆記
- go學習筆記劃重點Go筆記
- 【Go學習筆記16】解析xmlGo筆記XML
- 【Go學習筆記15】解析yamlGo筆記YAML
- 【Go】Go語言學習筆記-3-包Go筆記
- Go學習筆記 - Go 基礎語法(1)Go筆記