使用golang的channel的坑

2021-09-20 22:03:31 字數 3064 閱讀 6839

很多時候我們經過使用有緩衝channel作為通訊控制的功能,以至有一些誤解和坑出現。

執行下面**。

1

2

3

4

5

6

7

8

9

10

11

12

13

packagemainimport ("time"

"math/rand")func main()

}()    go getcache(cache)    go getcache(cache)    go getcache(cache)

time.sleep(3*time.second)

}func getcache(cache <-chanint)

}

}

多執行幾次看看結果,並不是每一次都是可以順序輸出的,有快取channel是亂序的。因為這裡讓一些同學誤解了,我在此多解釋一下。

針對通道的傳送和接收操作都是可能造成相關的goroutine阻塞。試想一下,有多個goroutine向同乙個channel傳送資料而被阻塞,如果還channel有多餘的快取空間時候,最早被阻塞的goroutine會最先被喚醒。也就是說,這裡的喚醒順序與傳送操作的開始順序是一致的,對接收操作而言亦為如此。無論是傳送還是接收操作,執行時系統每次只會喚醒乙個goroutine。 而這裡的亂序是指,如果像使用channel快取中多個goroutine實現順序是正確的,因為每乙個goroutine搶到處理器的時間點不一致,所以不能保證順序。

如下**。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

packagemainimport ("fmt"

"sync"

"time")var wg = sync.waitgroup{}func main() func insert(bf chan string)

wg.done()

}func sprint(s string) func get(bf chan string)

}()

}

}

很多同學乍一看以為定義了

1bf := make(chan string,64)

就是說該程式的併發度控制在了64,執行就會發現記憶體一直在增長。 因為get()函式中啟動的goroutine會越來越多,因為get()每讀取乙個資料,insert()就會往channel插入一條資料,此時併發度就不是64了。 需要修改為:

12

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

packagemainimport ("fmt"

"sync"

"time")var wg = sync.waitgroup{}func main()

wg.wait()

}func insert(bf chan string)

wg.done()

}func sprint(s string) func get1(bf chan string)

}

}

golang中併發sync和channel

golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...

golang中併發sync和channel

golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...

golang中併發sync和channel

golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...