I am attempting to get two go routines to increment an integer.
package main
import (
"fmt"
"sync"
)
var sum = 0
var wg sync.WaitGroup
func main() {
wg.Add(2)
ch := make(chan int)
ch <- sum
go func() {
sum = <-ch
sum++
ch <- sum
defer wg.Done()
}()
go func() {
sum = <-ch
sum++
ch <- sum
defer wg.Done()
}()
wg.Wait()
i := <-ch
close(ch)
fmt.Println(i)
}
The error is:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/peter/work/src/misc2/go-routines-addition/main.go:14 +0x72
exit status 2
>>
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/peter/work/src/misc2/go-routines-addition/main.go:14 +0x72
exit status 2
At the moment when you issue ch <- sum
You main thread blocks but there are no other goroutines available because you defined and run after that line. Move that line before wg.Wait() and it could do the trick…
I use to put some println to trace what it is going on.
package main
import (
"fmt"
"sync"
)
var sum = 0
var wg sync.WaitGroup
func main() {
wg.Add(1)
ch := make(chan int)
go func() {
defer func() {
fmt.Println("(1) defering...")
wg.Done()
}()
fmt.Println("(1) getting channel...")
sum = <-ch
fmt.Println("(1) sum=", sum)
sum++
fmt.Println("(1) Increment=", sum)
ch <- sum
fmt.Println("(1) put in channel...")
}()
go func() {
defer func() {
fmt.Println("(2) defering...")
wg.Done()
}()
fmt.Println("(2) getting channel...")
sum = <-ch
fmt.Println("(2) sum=", sum)
sum++
fmt.Println("(2) Increment=", sum)
ch <- sum
fmt.Println("(2) put in channel...")
}()
fmt.Println("(Main) Sending sum to channel:", sum)
ch <- sum
fmt.Println("(Main) Waiting...")
wg.Wait()
fmt.Println("(Main) Reading from channel...")
i := <-ch
fmt.Println("(Main) Closing channel...")
close(ch)
fmt.Println("(Main) Reading last value...")
fmt.Println(i)
}
After playing around with your solution I noticed that you only add 1 to wg.Add(1).
There are two go routines, it was my understanding that you add one per go routine.
Could you explain this please?
Yes, you right and it make sense to used “2” instead of “1” because there are two goroutines. If you use “2” you get the data race because a goroutine is ended as the code is running. The Data race condtion happens when in goroutine (1) issues “ch <- sum” and then control is given to main thread and wg.Wait() is executed without a goroutine is running.
Let’s continue how to solve…