Go 语言提供了更加方便的并发编程方式(goroutine),通过go
关键字调用新的协程,而不需要像java或者类似的语言去封装一些线程池之类的东西,这使得go语言对并发编程显得非常友好
我们可以很方便的新建一个协程
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-08-25 15:15:43
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"time"
)
func download() {
fmt.Println("Download begins...")
time.Sleep(time.Second * time.Duration(5))
fmt.Println("Download successful")
}
func main() {
fmt.Println("Main begins...")
go download()
fmt.Println("Main end")
}
/*
Main begins...
Main end
*/
通过运行这个程序,我们发现download函数好像根本没有运行!这是因为,这个程序在main函数推出后就结束了,而通过go关键字生成新的协程会花费一定的时间,这就导致,在主协程结束以后,所有的子协程都被强行结束,这就是为什么download函数根本没有运行。为了验证这个说法,我们让主协程多跑一会儿
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-08-25 15:19:08
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"time"
)
func download() {
fmt.Println("Download begins...")
time.Sleep(time.Second * time.Duration(5))
fmt.Println("Download successful")
}
func main() {
fmt.Println("Main begins...")
go download()
time.Sleep(time.Second * time.Duration(6))
fmt.Println("Main end")
}
/*
Main begins...
Download begins...
Download successful
Main end
*/
可以看到这里子协程是已经正常运行了的。但是,我们以后所有的程序都需要使用sleep函数来阻塞么?这显然是不合理的,因此,go提供了一些其他的方法
比如使用sync
方式
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-08-25 15:23:44
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func download() {
fmt.Println("Download begins...")
time.Sleep(time.Second * time.Duration(5))
fmt.Println("Download successful")
wg.Done()
}
func main() {
wg.Add(1)
fmt.Println("Main begins...")
go download()
wg.Wait()
fmt.Println("Main end")
}
这种方式要求所有的子协程之间没有通信,主协程会一直阻塞,直到所有的子协程都结束
那么,如果我们的子协程之间需要通信呢?是的,go也提供了通道(channel)的方式来解决这个问题
/*
* @Author: NorthCityChen
* @LastEditTime: 2021-08-25 15:28:44
* @Description:
* @Website: https://grimoire.cn
* Copyright (c) NorthCityChen All rights reserved.
*/
package main
import (
"fmt"
"time"
)
var ch = make(chan string, 10)
func download() {
fmt.Println("Download begins...")
sleepTime := time.Second * time.Duration(5)
time.Sleep(sleepTime)
fmt.Println("Download successful")
ch <- sleepTime.String()
}
func main() {
fmt.Println("Main begins...")
go download()
go download()
go download()
for i := 0; i < 3; i++ {
msg := <-ch
fmt.Println(msg)
}
fmt.Println("Main end")
}
通道依然会阻塞主协程,等待子协程的结束,但是允许协程之间的数据交换
作者:NorthCity1984
出处:https://grimoire.cn/golang/go13.html
版权:本文《Go 学习笔记:并发编程》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
出处:https://grimoire.cn/golang/go13.html
版权:本文《Go 学习笔记:并发编程》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任