Golang对并发的支持相对简单,采用的是Goroutine的机制,类似于协程。
采用Go关键字就能实现。
Goroutine 基础
第一种情况
func main() {
for i := 0; i < 10; i++ {
go func(i int) {
fmt.Println(i)
}(i)
}
}
猜猜以上代码的输出,结果是什么都不输出。
为什么呢,明明我用go开启了10个并发协程为什么什么都不输出呢?
原因:当走完for循环的时候,main方法就结束了。这个时候 程序就会释放所有资源。所以go创建的并发func并不会执行。
第二种情况
func main() {
wg := new(sync.WaitGroup)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
fmt.Println(i)
}(i)
}
wg.Wait()
}
先介绍一下sync.WaitGroup,点开可以看文档。
wg.Add(delta int)方法就是来设定应等待的线程的数量。
wg.Done() Done方法减少WaitGroup计数器的值,应在线程的最后执行。
wg.Wait() Wait方法阻塞直到WaitGroup计数器减为0。
这样写的目的就是让main方法阻塞。
那么输出的话就会很随机,因为你也不知道哪个线程会先跑完。
附加runtime方法
func main() {
runtime.GOMAXPROCS(2)
wg := new(sync.WaitGroup)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
if i == 3 {
runtime.Goexit()
}
fmt.Println(i)
}(i)
}
wg.Wait()
}
runtime.GOMAXPROCS(2) OMAXPROCS设置可同时执行的最大CPU数,来实现多核多线程并行。
runtime.Goexit() Goexit终止调用它的go程。其它go程不会受影响。Goexit会在终止该go程前执行所有defer的函数。
Goroutine通信 --> Channel
Channel的设计为了实现Goruntine直接的通信。值得一提的是Channel是值类型,这点需要注意。
//创建
chan = make(chan int)
使用channel在俩goroutine间传递消息
func main() {
runtime.GOMAXPROCS(4)
ch := make(chan int)
go add(1, 2, ch)
go printAaddB(ch)
}
func add(a int, b int, ch chan int) {
ch <- a + b
}
func printAaddB(ch chan int) {
fmt.Println(<-ch)
}
这样便实现了chennel传递消息。
参考
以上内容如有错误,请指出。
Go 学习笔记 第四版 雨痕
Go 中文文档