go语言并发编程
goroutine
轻量级 线程
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
使用go关键字
1 2
| //检测数据冲突 go run -race main.go
|
channel
goroutine之间通信
不要通过共享内存来通信;通过通信来共享内存
chan<- int 表示只发送不能接收
<-chan int 表示只接收不能发送
所有的并发问题 都可以用一致的、简单的既定的模式来规避。所有可能的话,将变量限定在goroutine内部,如果是多个goroutine都需要访问的变量,使用互斥条件来访问
go的调度器,当一个goroutine调用了time.Sleep等 阻塞时,调度器会使其进入休眠并开始执行另一个goroutine直到时机到了再去唤醒第一个goroutine。这种调度不需要进入内核的上下文,所以比线程的代价低
几个 runtime包中处理goruntine的函数
Goexit
退出当前执行的goroutine,但是defer函数还会继续调用
Gosched
让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
NumCPU
返回 CPU 核数量
NumGoroutine
返回正在执行和排队的任务总数
GOMAXPROCS
用来设置可以并行计算的CPU核数的最大值,并返回之前的值。
example
chan 的方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package main
import "fmt"
func main() { pings := make(chan string, 1) pongs := make(chan string, 1) ping(pings, "password message") pong(pings, pongs) fmt.Println(<-pongs) }
//pings 只能用来发送channel func ping(pings chan<- string, msg string) { pings <- msg }
//pings 只能用来接收channel func pong(pings <-chan string, pongs chan<- string) { msg := <-pings pongs <- msg }
|
select
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package main
import ( "fmt" "time" )
func main() {
c1 := make(chan string) c2 := make(chan string)
go func() { time.Sleep(time.Second * 1) c1 <- "one" }()
go func() { time.Sleep(time.Second * 1) c2 <- "two" }()
for i := 0; i < 2; i++ { select { case msg1 := <-c1: fmt.Println("received", msg1) case msg2 := <-c2: fmt.Println("received", msg2) } }
}
|