【Go】fatal error: all goroutines are asleep - deadlock!

目录

1、Channel

 2、fatal error: all goroutines are asleep - deadlock!

3、有缓冲的通道


1、Channel

在Go语言中,Channel(通道)是用于goroutine之间进行通信和同步的一种机制。它可以在一个goroutine中发送数据到通道,然后在另一个goroutine中接收数据。通道是类型相关的,也就是说通道中传输的数据必须是同一类型。

channel是一种类型,一种引用类型。声明通道类型的格式如下:

  var 变量 chan 元素类型  

通道是引用类型,通道类型的空值是nil。

var ch chan int
fmt.Println(ch) // <nil>

声明的通道后需要使用make函数初始化之后才能使用。

package main

import "fmt"

func main() {
	var f chan int
	fmt.Println(f)
	f = make(chan int)
	fmt.Println(f)
}

 2、fatal error: all goroutines are asleep - deadlock!

package main

import "fmt"

func main() {
	var f chan int
	fmt.Println(f)
	f = make(chan int)
	fmt.Println(f)

	f <- 10
}

 为什么会出现deadlock错误呢?

因为我们使用ch := make(chan int)创建的是无缓冲的通道,无缓冲的通道只有在有人接收值的时候才能发送值。

就像你住的小区没有快递柜和代收点,快递员给你打电话必须要把这个物品送到你的手中,简单来说就是无缓冲的通道必须有接收才能发送。

那如何解决这个问题呢?

一种方法是启用一个goroutine去接收值,例如:

package main

import "fmt"

func recv(c chan int) {
	ret := <-c
	fmt.Println("接收成功", ret)
}

func main() {
	var f chan int
	fmt.Println(f)
	f = make(chan int)
	fmt.Println(f)

	go recv(f)

	f <- 10
}

 无缓冲通道上的发送操作会阻塞,直到另一个goroutine在该通道上执行接收操作,这时值才能发送成功,两个goroutine将继续执行。相反,如果接收操作先执行,接收方的goroutine将阻塞,直到另一个goroutine在该通道上发送一个值。

使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。

3、有缓冲的通道

我们可以在使用make函数初始化通道的时候为其指定通道的容量,例如:

package main

import "fmt"

func main() {
	ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
	ch <- 10
	fmt.Println("发送成功")
}

 只要通道的容量大于零,那么该通道就是有缓冲的通道,通道的容量表示通道中能存放元素的数量。就像你小区的快递柜只有那么个多格子,格子满了就装不下了,就阻塞了,等到别人取走一个快递员就能往里面放一个。

猜你喜欢

转载自blog.csdn.net/fanjufei123456/article/details/131961056