goroutine通道(channel)死锁与处理

goroutine死锁

场景一:

package main

func main() {
	ch := make(chan int)
	<- ch // 阻塞main goroutine, 通道被锁
}

输出:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
//无缓冲通道上,没有数据写入通道内,阻塞ch,通道被锁

场景二:

func main() {
	cha, chb := make(chan int), make(chan int)

	go func() {
		cha <- 1 // cha通道的数据没有被其他goroutine读取走,堵塞当前goroutine
		chb <- 0
	}()

	<- chb // chb 等待数据的写
}

输出

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
//无缓冲通道上cha数据没有被读取,发送阻塞被锁

死锁产生原因总结:

goroutine的非缓冲通道里头一定要一进一出,成对出现才行。 上面例子属于:一:流出无流入;二:流入无流出

例外情况:

func main() {
    ch := make(chan int)
    go func() {
       ch <- 1
    }()
}
//main函数自己先跑完了,所以就没有数据流入主的goroutine,就不会被阻塞和报错

goroutine的死锁处理

1、写入通道:

func main() {
	ch := make(chan int)
	go func() {
		ch <- 1
	}()

	fmt.Println(<-ch) // 阻塞main goroutine, 通道被锁
}

2、把没取走的取走:

package main

func main() {
	cha, chb := make(chan int), make(chan int)

	go func() {
		cha <- 1 // cha通道的数据没有被其他goroutine读取走,堵塞当前goroutine
		chb <- 0
	}()

	<- cha // 取走
	<- chb // chb 等待数据的写
}

3、创建缓冲通道

package main

func main() {
	cha, chb := make(chan int, 3), make(chan int)
	go func() {
		cha <- 1 // cha通道的数据没有被其他goroutine读取走,堵塞当前goroutine
		chb <- 0
	}()

	<- chb // chb 等待数据的写
	
//因为cha容量为3,只要不超过三个就不会阻塞
}

zed
请先登录后发表评论
  • latest comments
  • 总共0条评论