Fatal error: all goroutines are asleep - deadlock!

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

Code can be found here:

https://play.golang.org/p/wyKGpqFWtmG

Any pointers to what I do wrong?

Not sure I understand what channels are for in your code.
Here is one way to do it:

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var sum int64

func main() {
	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		atomic.AddInt64(&sum, 1)
	}()

	go func() {
		defer wg.Done()
		atomic.AddInt64(&sum, 1)
	}()

	wg.Wait()
	fmt.Println(sum)
}

It is just an academic attempt to learn channels better.
Thank you for your help!

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)
}

Sweet, thank you!

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…

if you are learning golang you can follow these tutorial these are awesome
https://quii.gitbook.io/learn-go-with-tests/

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.