Go
GO语言并发编程
go语言并发编程
goroutine
轻量级 线程
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
使用go关键字
//检测数据冲突
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 的方向
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
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)
}
}
}