How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?

Mary-Kate Olsen
Release: 2024-10-27 01:21:02
Original
970 people have browsed it

How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?

Deadlock in Go with WaitGroup and Channel

In Go, a deadlock occurs when two or more goroutines wait indefinitely for the other to finish. In this example, we will explore a deadlock issue caused by an insufficient channel buffer and improper syncing of goroutines using a WaitGroup.

The Code

<code class="go">package main

import "fmt"
import "sync"

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>
Copy after login

The Issue

The code attempts to send 5 values over a buffered channel of size 4. However, when the channel is full, it blocks until a receiver becomes available. Since all goroutines that are sending have finished, none are available to receive from the channel.

Additionally, the goroutine that ranges over the channel (for c := range ch) also remains blocked indefinitely because it expects more values to arrive in the channel even though no more are being sent. This creates a deadlock where both senders and receivers are waiting on each other.

Solution 1: Increase Channel Buffer and Close It

One solution to avoid the deadlock is to increase the channel buffer size to a value greater than or equal to the number of sending goroutines. Additionally, the channel should be closed after all sends are complete, indicating that no more values will be received.

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>
Copy after login

Solution 2: Perform Done() in Receiving Goroutine

Another solution is to perform Done() in the receiving goroutine instead of in the main function. By doing so, the WaitGroup will not be decremented until the value has been received and consumed by the goroutine:

<code class="go">func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            ch <- m
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()
}</code>
Copy after login

The above is the detailed content of How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!