Why does passing a WaitGroup by value in Go channels lead to a deadlock?

Mary-Kate Olsen
Release: 2024-10-31 04:59:02
Original
418 people have browsed it

Why does passing a WaitGroup by value in Go channels lead to a deadlock?

Deadlock in Go Channel Due to Reference Passing

In Go, channels are a powerful communication mechanism, but they can lead to deadlocks if not used correctly. A deadlock occurs when two or more goroutines are waiting for each other to complete an operation, resulting in neither goroutine being able to proceed.

Consider the following Go program:

<br>package main</p>
<p>import (</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt"
"sync"
Copy after login
Copy after login

)

func push(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Copy after login
Copy after login

}

func pull(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Copy after login
Copy after login

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, wg)
go pull(c, wg)

wg.Wait()
Copy after login

}

When you run this program, it will panic with a deadlock error:

throw: all goroutines are asleep - deadlock!
Copy after login

The problem lies in how the WaitGroup is passed to the goroutines. In Go, structs are passed by value, which means that a copy of the WaitGroup is passed to each goroutine. When one goroutine calls Done on its copy, it has no effect on the original WaitGroup that was created in the main function.

To fix the deadlock, the WaitGroup pointer must be passed instead of the value. Here's the corrected code:

<br>package main</p><p>import (</p><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">"fmt"
"sync"
Copy after login
Copy after login

)

func push(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Copy after login
Copy after login

}

func pull(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Copy after login
Copy after login

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, &wg)
go pull(c, &wg)

wg.Wait()
Copy after login

}

By passing the WaitGroup pointer instead of the value, both goroutines have access to the same WaitGroup instance. When one goroutine calls Done, it decrements the count on the original WaitGroup, allowing the other goroutine to proceed.

The above is the detailed content of Why does passing a WaitGroup by value in Go channels lead to a deadlock?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Previous article:How can you Break a For Loop from Outside Its Scope in Golang? Next article:Why Are Methods on `T` Not Usable by `*T` in Go?
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
Latest Issues
Related Topics
More>
Popular Recommendations
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!