Golang并发编程之goroutine
0、Go语言中的并发编程
并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天)
并行:同一时刻执行多个任务(你和你朋友都在用微信和女朋友聊天)
Go语言的并发通过goroutine
实现。goroutine�
类似于线程,属于用户态的线程,我们可以根据需要创建成千上万个goroutine
并发工作。goroutine
是由Go语言的运行时(runtime)调度完成,而线程是由操作系统调度完成
Go 语言还提供channel
在多个goroutine
间进行通信。goroutine
和channel
是Go语言继承的CSP并发模式的重要实现基础
1、goroutine简介
在Java和C++中我们要实现并发编程的时候,必须要自己维护一个线程池,并且需要自己去包装一个又一个的任务,同时还要自己去调度线程执行任务并维护上下文切换。
Go语言编程中你不需要自己去写进程、线程、协程、你的技能包里只有一个技能goroutine
,当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,开启一个goroutine
去执行这个函数就可以了。
2、goroutine应用
Go语言中使用goroutine
非常简单,只需要在调用函数的时候在前面加上一个go
关键字,就可以为一个函数创建一个goroutine
。
一个
goroutine
必须对应一个函数,可以创建多个goroutine
去执行同一个函数
package main
import (
"fmt"
"time"
)
// goroutine
func hello(i int){
fmt.Println("hello",i)
}
// 程序启动之后会创建一个主goroutine去执行
func main(){
for i:=0;i<100;i++ {
//go hello(i) // 开启一个单独的goroutine去执行hello函数(任务)
go func(i int){
fmt.Println(i)
}(i)
}
fmt.Println("main")
time.Sleep(time.Second)
// main函数结束了 由main函数启动的goroutine也都结束了
}
在Go语言中实现并发就是这么简单,我们还可以启动多个goroutine
。让我们再举一个例子(这里使用sync.WaitGroup来实现goroutine
的同步)
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func f(i int){
defer wg.Done() // 计数器减1
time.Sleep(time.Millisecond * time.Duration(rand.Intn(300)))
fmt.Println(i)
}
var wg sync.WaitGroup
func main(){
//f()
for i:=0;i<10;i++{
wg.Add(1) // 计数器加1
go f(i)
}
// 如何知道这10个goroutine都结束了
wg.Wait() // 等待wg的计数器减为0
}
3、GOMAXPROCS
Go运行时的调度器会使用GOMAXPROCS
参数来确定需要使用多少OS线程来同时执行Go代码,默认值是机器上的CPU核心数。
package main
import (
"fmt"
"runtime"
"sync"
)
var wg sync.WaitGroup
func a(){
defer wg.Done()
for i:=0;i<10;i++{
fmt.Printf("A:%d\n",i)
}
}
func b(){
defer wg.Done()
for i:=0;i<10;i++{
fmt.Printf("B:%d\n",i)
}
}
func main(){
runtime.GOMAXPROCS(1) // 指定在N个核心数上调度
wg.Add(2)
go a()
go b()
wg.Wait()
}