Go 知识点(02)— channel 使用不当导致的 deadlock

运行下面这段代码输出的结果是什么?

package main

import (
	"fmt"
)

func main() {
    
    
	c := make(chan string) //	创建一个无缓冲的通道
	c <- "hello world"
	fmt.Println(<-c)
}

答案是:会发生死锁

fatal error: all goroutines are asleep - deadlock!

原因是:对于无缓冲通道,发送方和接收方必须同时准备好才能保证消息的接收。而上面代码发送方和接收方都在 main goroutine 中,所以两者不可能同时运行,必须是一前一后,这也就导致了发送方在一直等待接收方,而接收方由于发送方阻塞而不能执行到,最终的结果是死锁。

发送方在发送消息到通道的时候,此时如果接收方还没有准备好,那么发送方就会一直阻塞着,等待着接收方的到来,如果接收方一直没在就会造成死锁。

如何解决这个问题呢?

我们要知道通道一般适用于不同的协程之间信息的交互,所以要解决上面问题,我们可以让发送方和接收方处于不同的协程中。

见下面代码

func main() {
    
    
	ch := make(chan string) //	创建一个无缓冲的通道

	// 启动一个协程
	go func(c chan string) {
    
    
		c <- "hello world"
	}(ch)

	fmt.Println(<-ch)
}

输出结果如下:

hello world

而有缓冲通道则不会出现上述的死锁问题

func main() {
    
    
	c := make(chan string, 1) // 容量为 1 的有缓冲通道
	c <- "hello world"
	fmt.Println(<-c)
}

运行后可以正常打印结果,所以有缓冲的通道不要求发送方和接收方同时准备好,发送方将消息发送到通道中之后,就可以走了,接收方不管什么时候到,只需通道中消息直接取走就可以了。

但是我们继续看下面这段代码

func main() {
    
    
	c := make(chan string, 1) // 容量为 1 的有缓冲通道
	c <- "hello"
	c <- "world"
	fmt.Println(<-c)
}

运行结果是什么呢?

fatal error: all goroutines are asleep - deadlock!

为什么有缓冲通道也会有死锁呢?

原因在于此处创建了容量为 1 的缓冲通道,而在代码中连续发送两条消息,当发送第一条消息后通道里面的消息个数就和容量相等了,此时再发送就只能等待通道中的消息被拿走才能继续发送,在通道里面的消息没有取走之前,发送方就会一直阻塞着。

即有缓冲的通道,当通道信息个数等于通道容量时,发送方就会一直阻塞,直到接收方将消息取走,有剩余的容量时发送方才会继续发送。

那么,如果发送发已经发送完毕,接收方一直等待取消息,会发生什么情况?

func main() {
    
    
	ch := make(chan string)
	go func() {
    
    
		ch <- "hello"
		ch <- "world"
	}()

	for data := range ch {
    
    
		fmt.Println(data)
	}
}

输出结果:

hello
world
fatal error: all goroutines are asleep - deadlock!

又又发生死锁了,这又是为什么呢?

原因就在于发送方发送完成后就不管了,但是呢?接收方又不知道发送方有没有发送完成,就傻乎乎的一直等待下去,最后就造成死锁了。

如何解决呢?

我们只需要在发送方发送完毕后告诉接收方,我已经发送完了,你取了最后一个消息就回家吧,媳妇、儿子等你回家呢。

怎样告诉接收方呢?很简单使用 close() 关闭通道即可。

func main() {
    
    
	ch := make(chan string)
	go func() {
    
    
		ch <- "hello"
		ch <- "world"
		close(ch)   // 发送完毕后关闭通道
	}()

	for data := range ch {
    
    
		fmt.Println(data)
	}
}

所以呢,我们也要养成 凡事有交代,件件有着落,事事有回音 的好习惯,要及时反馈当前的状态。

猜你喜欢

转载自blog.csdn.net/wohu1104/article/details/115336793