goroutines
goroutines并不对应着操作系统中的线程,它可以由多个线程来执行 gorouinte 之间又不像进程之间那样,使用独立的内存空间,它们使用共享的内存空间,因此它们存在读写同步的问题,使用go的channel。
gc-compiler对应着是真正的goroutines,每个都对应着一个或若干个线程,而gccgo则是为每一个goroutine建立一个线程。
不要试图用print语句来显示多个进程间的真实顺序,因为print的延迟会导致显示的不是真正的顺序
channel
- 非缓存的channel
channel是无法暂时混存数据,因此发送端会被阻塞,除非接受端从channel中接收数据
非缓存的channel很适合用于多个goroutines之间同步1
2
3
4
5
6
7
8
9
10
11package main
import (
“fmt” )
func f1(in chan int) {
fmt.Println(<-in)
}
func main() {
out := make(chan int)
out <- 2
go f1(out)
}
这段代码中总会出现deadlock作用。因为main这个goroutine运行到out<-2时,因为是非缓存的,所以阻塞了,后面的f1还没有启动,因此所有的goroutine都进入了死亡状态
- select和channel的使用
1 |
|
相当于是在从几个goroutine中选择已经有结果了的进行处理,如果外面加上一个无限循环的话,就能够达到不断处理的效果了
针对以上这个代码
如果有多个通道已经ready了的话,就随机从中选出一个
如果没有ready的话它会等待
如果添加了default的话,在没有一个是ready的情况下将会执行default的代码
缓存的channel
cap函数可以得到buffe的大小
发送端当且仅当channel满了的时候阻塞,接受端当且仅当channel空了的时候阻塞利用goroutines和channel来进行并行编程
可以讲channel当作一个信号量,用于锁住资源
利用for循环的并行化1
2
3
4
5for i, v := range data {
go func (i int, v float64) {
}
doSomething(i, v)
... } (i, v)利用缓存的channel来实现信号量
channel的容量是我们想要进行同步的资源个数
channel的现有长度是现在被占用的资源个数
channel的容量-长度是现在可用的资源的个数channel factory 模式
可以在主goroutine中创建channel然后传入函数中,也可以在函数中创建channel然后返回到调用它的goroutine中来实现同步指定channel的类型只发送或只接收
1
2var send_only chan<- int // channel can only receive data
var recv_only <-chan int // channel can only send data