分享 Golang 并发基础库,扩展以及三方库的一些常见问题、使用介绍和技巧,以及对一些并发库的选择和优化探讨。
不要通过共享内存进行通信;相反,通过通信来共享内存。
主要调度器结构是 M,P,G
P 的数量由环境变量中的 GOMAXPROCS 决定,通常来说和核心数对应。
用户空间线程和内核空间线程映射关系有如下三种:
关系如图,灰色的 G 则是暂时还未运行的,处于就绪态,等待被调度,这个队列被 P 维护
注: 简单调度图如上,有关于 P 再多个 M 中切换,公共 goroutine 队列,M 从线程缓存中创建等步骤没有体现,复杂过程可以参考文章简单了解 goroutine 如何实现。
- // 创建 channel
- a := make(chan int)
- b := make(chan int, 10)
- // 单向 channel
- c := make(chan<- int)
- d := make(<-chan int)
tip:
v, ok := <-a // 检查是否成功关闭(ok = false:已关闭)
- use channel
- ci := make(chan int)
- cj := make(chan int, 0)
- cs := make(chan *os.File, 100)
-
- c := make(chan int)
- go func() {
- list.Sort()
- c <- 1
- }()
- doSomethingForValue
- <- c
-
- func Server(queue chan *Request) {
- for req := range queue {
- sem <- 1
- go func() {
- process(req)
- <- sem
- }()
- }
- }
-
- func Server(queue chan *Requet) {
- for req := range queue {
- sem <- 1
- go func(req *Request) {
- process(req)
- <- sem
- }(req)
- }
- }
-
- func Serve(queue chan *Request) {
- for req := range queue {
- req := req
- sem <- 1
- go func() {
- process(req)
- <-sem
- }()
- }
- }
- c := make(chan bool)
- go func() {
- // close 的 channel 会读到一个零值
- close(c)
- }()
- <-c
开源项目【是一个支持集群的 im 及实时推送服务】里面的基准测试的案例
资料领取直通车:Golang云原生最新资料+视频学习路线https://docs.qq.com/doc/DTllySENWZWljdWp4
Go语言学习地址:Golang DevOps项目实战https://ke.qq.com/course/422970?flowToken=1043212
- func main() {
- ret := make(chan string, 3)
- for i := 0; i < cap(ret); i++ {
- go call(ret)
- }
- fmt.Println(<-ret)
- }
- func call(ret chan<- string) {
- // do something
- // ...
- ret <- "result"
- }
注: 协同多个 goroutines 方案很多,这里只展示 channel 的一种。
- limits := make(chan struct{}, 2)
- for i := 0; i < 10; i++ {
- go func() {
- // 缓冲区满了就会阻塞在这
- limits <- struct{}{}
- do()
- <-limits
- }()
- }
- for {
- select {
- case a := <- testChanA:
- // todo a
- case b, ok := testChanB:
- // todo b, 通过 ok 判断 tesChanB 的关闭情况
- default:
- // 默认分支
- }
- }
- func worker(testChan chan bool) {
- for {
- select {
- // todo some
- // case ...
- case <- testChan:
- testChan <- true
- return
- }
- }
- }
-
- func main() {
- testChan := make(chan bool)
- go worker(testChan)
- testChan <- true
- <- testChan
- }
- testChan := make(chan bool)
- close(testChan)
-
- zeroValue := <- testChan
- fmt.Println(zeroValue) // false
-
- testChan <- true // panic: send on closed channel
注: 如果是 buffered channel
, 即