0
点赞
收藏
分享

微信扫一扫

Golang并发——Goroutine、runtime包、channel

逸省 2022-02-11 阅读 90

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 如何利用无缓冲的通道来共享一个值:

举报

相关推荐

0 条评论