1 Goroutine

1.1 Go关键字

Goroutine 是 Go 程序中最基本的并发执行单元。每一个 Go 程序都至少包含一个 goroutine——main goroutine,当 Go 程序启动时它会自动创建。

  1. // 创建一个新的 goroutine 运行函数f--go f()
  2. //匿名函数也支持使用go关键字创建 goroutine 去执行。 --go func(){}()
  3. package main
  4. import (
  5. "fmt"
  6. "sync"
  7. )
  8. // 声明全局等待组变量
  9. var wg sync.WaitGroup
  10. func hello() {
  11. fmt.Println("hello")
  12. wg.Done() // 告知当前goroutine完成
  13. }
  14. func main() {
  15. wg.Add(1) // 登记1个goroutine
  16. go hello()
  17. fmt.Println("你好")
  18. wg.Wait() // 阻塞等待登记的goroutine完成
  19. }

1.1 GOMAXPROCS

Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个 OS 线程来同时执行 Go 代码。默认值是机器上的 CPU 核心数。例如在一个 8 核心的机器上,GOMAXPROCS 默认为 8。Go语言中可以通过runtime.GOMAXPROCS函数设置当前程序并发时占用的 CPU逻辑核心数。(Go1.5版本之前,默认使用的是单核心执行。Go1.5 版本之后,默认使用全部的CPU 逻辑核心数。)

2 channel

2.1channel定义与使用
如果说 goroutine 是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个 goroutine 发送特定值到另一个 goroutine 的通信机制。
语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

//var 变量名称 chan 元素类型
// 声明一个传递整型的通道
var ch1 chan int
//make(chan 元素类型, [缓冲大小])
ch2 := make(chan int)
ch2 := make(chan bool, 1)
// 只接收通道,只能接收不能发送
<- chan int 
// 只发送通道,只能发送不能接收
chan <- int 


func f2(ch chan int) {
    for {
        v, ok := <-ch
        if !ok {
            fmt.Println("通道已关闭")
            break
        }
        fmt.Printf("v:%#v ok:%#v\n", v, ok)
    }
}

func main() {
    ch := make(chan int, 1)
    ch <- 1
  ch <- 2
    close(ch)
    f2(ch)
}

image.png

2.1select多路复用

select {
case <-ch1:
    //...
case data := <-ch2:
    //...
case ch3 <- 10:
    //...
default:
    //默认操作
}
  • 可处理一个或多个 channel 的发送/接收操作。
  • 如果多个 case 同时满足,select 会随机选择一个执行。
  • 对于没有 case 的 select 会一直阻塞,可用于阻塞 main 函数,防止退出。

3 锁

3.1互斥锁