JOE'S BLOG

好记性不如烂键盘

0%

GO语言并发编程

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)
}
}

}