Goroutine:
Goroutine的创建:
演示:
func main() {
go goroutineTest01()
go goroutineTest02()
for {
}
}
func goroutineTest01() {
for i := 0; i < 10; i++ {
fmt.Println("goroutineTest01执行")
time.Sleep(1000 * time.Millisecond)
}
}
func goroutineTest02() {
for i := 0; i < 10; i++ {
fmt.Println("goroutineTest02执行")
time.Sleep(1000 * time.Millisecond)
}
}
runtime包:
runtime.Gosched()
用于让出CPU时间片,让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次再获得cpu时间轮片的时候,从该出让cpu的位置恢复执行。有点像跑接力赛,A跑了一会碰到代码runtime.Gosched() 就把接力棒交给B了,A歇着了,B继续跑。
func main() {
go func() {
for {
fmt.Println("我不让出时间片")
}
}()
for {
runtime.Gosched() // 让出当前时间片
fmt.Println("我让出时间片")
}
}
runtime.Goexit()
将立即终止当前 goroutine 执⾏,调度器确保所有已注册 defer延迟调用被执行。Goexit之前注册的defer会生效,之后不会。
func main() {
go func() { // Goexit直接退出func
fmt.Println("走我吗——1")
goexit()
fmt.Println("走我吗——2")
}()
for {
}
}
func goexit() {
//return
fmt.Println("走我吗——3")
runtime.Goexit() // 退出当前go程
defer fmt.Println("走我吗——4")
}
runtime.GOMAXPROCS()
用来设置可以并行计算的CPU核数的最大值,并返回上一次的核心数,如果是第一次调用就返回默认值。
func main() {
// func GOMAXPROCS(n int) int {} 参数是要设置的核心数,返回值是上一次设置的核心数
num := runtime.GOMAXPROCS(1)
fmt.Println("上一次设置核心数为:", num)
for {
// 0和1会一直交替打印,如果用GOMAXPROCS限制1个核心,那么谁抢到谁就一直跑
go fmt.Println(0)
fmt.Println(1)
}
}
channel:
channel分为两个端:
定义channel变量:
发送和接收数据语法:
channel <- value //发送value到channel
<-channel //接收并将其丢弃
x := <-channel //从channel中接收数据,并赋值给x
x, ok := <-channel //功能同上,同时检查通道是否已关闭或者是否为空
演示:
func main() {
go channelTest01()
go channelTest02()
for {
}
}
// 定义channel
var channel = make(chan int)
// 定义一个公共操作类
func print(s string) {
for _, ch := range s {
fmt.Printf("%c", ch)
time.Sleep(300 * time.Millisecond)
}
}
// 定义两个人使用打印机
func channelTest01() {
print("person01")
channel <- 1 // person01负责写的操作,随便写的数字都行,相当于规定了两个方法的执行顺序
}
func channelTest02() {
<-channel // person02负责读channel中的数据,也就是先把person01的数据读出来才会继续执行person02的任务
//num := <-channel // person02负责读channel中的数据,也就是先把person01的数据读出来才会继续执行person02的任务
// 如果一个写,一个没读,或者是一个读一个没写就会阻塞
print("person02")
//fmt.Println(num) //也可以定义一个变量存起来
}
无缓冲的channel:
无缓冲的通道(unbuffered channel)是指在接收前没有能力保存任何值的通道。
这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作。否则,通道会导致先执行发送或接收操作的 goroutine 阻塞等待。
这种对通道进行发送和接收的交互行为本身就是同步的。其中任意一个操作都无法离开另一个操作单独存在。
阻塞:由于某种原因数据没有到达,当前协程(线程)持续处于等待状态,直到条件满足,才接触阻塞。
同步:在两个或多个协程(线程)间,保持数据内容一致性的机制。
下图展示两个 goroutine 如何利用无缓冲的通道来共享一个值: