这是我参与「第五届青训营 -后端场」笔记创作活动的的第2篇笔记。 下面是我的学习总结:
1.并发与并行
- 并发:可以理解为去买东西,有两列队,但是只有一个售卖窗口。
- 并行:就相当去买东西,有两列队,也有两个售卖窗口,一个窗口前一列队。
go天生支持并发,在go中内置实现了任务的调度和管理。并发由协程(goroutine)实现,类似于线程。创建goroutine只需要在函数前加一个go关键字,当我们需要并发时,只需要把任务写到函数中,然后使用go关键字开启一个goroutine去执行即可。
一般情况下,go语言是串行执行。这时,程序只有一个goroutine即mian函数。
package main
import "fmt"
func main() {
seeHello()
fmt.Println("hello main")
}
func seeHello() {
fmt.Println("hello func")
}
然后,我们给main函数中的seeHello()函数前面加一个go关键字,即给seeHello()函数开一个goroutine。
package main
import "fmt"
func main() {
go seeHello()
fmt.Println("hello main")
}
func seeHello() {
fmt.Println("hello func")
}
这时我发现输出的只有hello main,没有输出hello func。因为当给seeHello()函数单独开一个goroutine时,程序不再是串行执行,seeHello()函数与main函数不是同一个线程,seeHello()函数还没来得及执行,main函数就执行结束了。我们可以添加time.Sleep()让main函数浅睡一会,等一下seeHello()函数。
package main
import (
"fmt"
"time"
)
func main() {
go seeHello()
fmt.Println("hello main")
time.Sleep(time.Second)
}
func seeHello() {
fmt.Println("hello func")
}
而当有多个goroutine时,我们再让main函数sleep,就可能会出现不知道什么时候结束的情况。这时我们就需要使用sync.WaitGroup来解决这个问题。
package main
import (
"fmt"
"sync"
)
func main() {
HelloGoroutine()
}
func HelloGoroutine() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
fmt.Println("hello goroutine:", fmt.Sprint(j))
}(i)
}
wg.Wait()
}
以上就是我今天的学习收获。