Home  >  Article  >  Backend Development  >  Why Does Using sync.WaitGroup with External Functions Lead to Deadlock?

Why Does Using sync.WaitGroup with External Functions Lead to Deadlock?

DDD
DDDOriginal
2024-11-06 19:43:02643browse

Why Does Using sync.WaitGroup with External Functions Lead to Deadlock?

Using sync.WaitGroup with External Functions

In a program, you may encounter issues when using sync.WaitGroup with functions defined outside the main function. Let's explore this situation.

Problem:

Consider the following code:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan int)
    var wg sync.WaitGroup
    wg.Add(2)
    go Print(ch, wg) //
    go func(){

        for i := 1; i <= 11; i++ {
            ch <- i
        }

        close(ch)
        defer wg.Done()
    }()

    wg.Wait() //deadlock here
}

// Print prints all numbers sent on the channel.
// The function returns when the channel is closed.
func Print(ch <-chan int, wg sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
    defer wg.Done()
}</code>

Here, you aim for the program to print numbers from 1 to 11, but it occasionally only prints 1 to 10.

Error Analysis:

You're passing a copy of sync.WaitGroup to the Print function, which means it doesn't call the Done() method on the sync.WaitGroup you're waiting for in the main function.

Solution:

To resolve this issue, update the code as follows:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan int)

    var wg sync.WaitGroup
    wg.Add(2)

    go Print(ch, &wg)

    go func() {
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
        defer wg.Done()
    }()

    wg.Wait() //deadlock here
}

func Print(ch <-chan int, wg *sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
    defer wg.Done()
}</code>

This ensures that the Print function calls the Done() method on the same sync.WaitGroup you're waiting for in the main function.

Alternatively, you can restructure your code to remove the reliance on sync.WaitGroup in the Print function:

<code class="go">package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)

    go func() {
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
    }()

    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
}</code>

The above is the detailed content of Why Does Using sync.WaitGroup with External Functions Lead to Deadlock?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn