Home  >  Article  >  Backend Development  >  Why is the main coroutine blocked in this case, causing a deadlock?

Why is the main coroutine blocked in this case, causing a deadlock?

PHPz
PHPzforward
2024-02-09 15:42:09565browse

Why is the main coroutine blocked in this case, causing a deadlock?

In PHP, it is common for the main coroutine to be blocked, leading to deadlock. During the execution of the main coroutine, if it encounters blocking operations, such as network requests, IO operations, or waiting for the results of other coroutines, if there is no appropriate handling method, deadlock may occur. In this case, the main coroutine cannot continue to execute, and other coroutines cannot get the opportunity to execute, and the entire program reaches a deadlock. So why is the main coroutine blocked in this case, causing a deadlock? Let’s answer this below.

Question content

package main

import "fmt"

func square(numbers chan int, squares chan int) {
    for n := range numbers {
        squares <- n * n
    }
    close(squares)
}

func main() {
    numbers := make(chan int)
    squares := make(chan int)

    go square(numbers, squares)

    for i := 0; i < 10; i++ {
        numbers <- i
    }
    close(numbers)

    for s := range squares {
        fmt.Println(s)
    }
}

I mean, I know that for this code to work, the numbers should be sent to the numbers channel in a separate goroutine, like:

go func() {
for i := 0; i < 10; i++ {
    numbers <- i
}

}

Having said that, I find it hard to explain why the deadlock occurs. I'm well aware that the scheduler does not guarantee execution order. However, the first time you send to the numbers channel in the loop, the main goroutine is blocked, but then the scheduler may start executing the square goroutine, and then they communicate back and forth, which is not Is that so?

Workaround

The reason why the main goroutine is blocked is that in this case, after sending the data to the squares channel, you are not reading any value from the squares channel.

When you do numbers , your <code>go square goroutine will receive the value and send it to the squares channel. However, at the same time, your main Goroutine will not receive values ​​from the sqaures channel because your main Goroutine is still sending data to the Numbers channel.

This means your main coroutine will never execute this line for s := range squares and then it will cause a deadlock.

In order to run this code correctly, you can modify it as shown below.

package main

import "fmt"

func square(numbers chan int, squares chan int) {
    for n := range numbers {
        squares <- n * n
    }
    close(squares)

}

func main() {
    numbers := make(chan int)
    squares := make(chan int)

    go square(numbers, squares)

    go func() {
        for i := 0; i < 10; i++ {
            numbers <- i
        }
        close(numbers)
    }()

    for s := range squares {
        fmt.Println(s)
    }
}

The above is the detailed content of Why is the main coroutine blocked in this case, causing a deadlock?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete