Go knowledge points (02)-Deadlock caused by improper use of channel

What is the output of running the following code?

package main

import (
	"fmt"
)

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

The answer is: deadlock will occur

fatal error: all goroutines are asleep - deadlock!

The reason is: For an unbuffered channel, the sender and receiver must be prepared at the same time to ensure the reception of the message. The code above the sender and recipient are main goroutinein, it is not possible to run both at the same time, must be one after the other, which also led to the sender waits until the recipient, the sender and the receiver due to the obstruction can not be executed To the end, the final result is a deadlock.

When the sender sends a message to the channel, if the receiver is not ready at this time, the sender will always be blocked, waiting for the receiver to arrive. If the receiver has not been there, it will cause a deadlock.

How to solve this problem?

We need to know that the channel is generally applicable to the exchange of information between different coroutines, so to solve the above problems, we can make the sender and the receiver in different coroutines.

See the code below

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

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

	fmt.Println(<-ch)
}

The output is as follows:

hello world

However, if there is a buffer channel, the above deadlock problem will not occur.

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

The results can be printed normally after running, so the buffered channel does not require the sender and the receiver to be ready at the same time. After the sender sends the message to the channel, it can go. The receiver only needs the message in the channel when it arrives. Just take it away.

But we continue to look at the following code

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

What is the result of the operation?

fatal error: all goroutines are asleep - deadlock!

Why is there a deadlock even if there is a buffer channel?

The reason is that a buffer channel with a capacity of 1 is created here, and two messages are sent continuously in the code. When the first message is sent, the number of messages in the channel is equal to the capacity, and at this time, you can only wait for sending The message in the channel can only be sent if it is taken away. The sender will be blocked until the message in the channel is taken away.

That is, there is a buffered channel. When the number of channel information is equal to the channel capacity, the sender will continue to block until the receiver takes the message away and the sender will continue to send when there is remaining capacity.

So, if the send has been sent and the receiver has been waiting to fetch the message, what will happen?

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

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

Output result:

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

Deadlock happened again, why is this?

The reason is that the sender ignores it after sending it, but what? The receiver doesn't know whether the sender has completed the transmission, so it waits forever, and finally causes a deadlock.

How to solve it?

We only need to tell the receiver after the sender has finished sending it that I have finished sending it. You can go home after you take the last message. Daughter-in-law and son are waiting for you to go home.

How to tell the recipient? Very simple to use close()off the channel can be.

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

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

So, we have to develop everything has confessed, each piece is secured, everything has an echo good habits, timely feedback to the current state.

Guess you like

Origin blog.csdn.net/wohu1104/article/details/115336793