Fatal Error - All Goroutines are asleep! Deadlock - go

I'm confused as to why this code deadlocks. I'm getting a fatal error about the goroutines being asleep. I'm using a waitgroup to synchronize and wait for the goroutines to finish, as well as passing the address of the one waitgroup I created instead of copying. I tried with and without a buffer but still.
package main
import (
"fmt"
"sync"
)
func findMax(nums []int32) int32{
max:=nums[0]
for _, n := range nums{
if n > max{
max = n
}
}
return max
}
func findFreq(nums []int32, n int32) int32{
mp := make(map[int32]int32)
for _, num := range nums{
if _, ok := mp[num]; ok{
mp[num]+=1
}else{
mp[num]=1
}
}
if f, ok := mp[n]; ok{
return f
}else{
return -1
}
}
func performWork(ch chan int32, nums []int32, q int32, wg *sync.WaitGroup){
defer wg.Done()
seg:=nums[q-1:]
max:=findMax(seg)
freq:=findFreq(seg, max)
ch <- freq
}
func frequencyOfMaxValue(numbers []int32, q []int32) []int32 {
res := []int32{}
var wg sync.WaitGroup
ch := make(chan int32)
for _, query := range q{
wg.Add(1)
go performWork(ch, numbers, query, &wg)
}
wg.Wait()
for n := range ch{
res=append(res, n)
}
return res
}
func main() {
nums := []int32{5,4,5,3,2}
queries:=[]int32{1,2,3,4,5}
fmt.Println(frequencyOfMaxValue(nums,queries))
}

The workers are blocked waiting for main goroutine to receive on the channel. The main goroutine is blocked waiting for the workers to complete. Deadlock!
Assuming that you get past this deadlock, there's another deadlock. The main goroutine receives on ch in a loop, but nothing closes ch.
Remove the deadlocks by running another goroutine to close the channel when the workers are done.
for _, query := range q {
wg.Add(1)
go performWork(ch, numbers, query, &wg)
}
go func() {
wg.Wait() // <-- wait for workers
close(ch) // <-- causes main to break of range on ch.
}()
for n := range ch {
res = append(res, n)
}

Related

How to execute multiple goroutines in parallel without a Deadlock

So I have been trying to run mutliple goroutines in parallel using a WaitGroup. Whatever I try I always end up with a "fatal error: all goroutines are asleep - deadlock!"
This is what my code looks like right now:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch := make(chan time.Duration)
var wg sync.WaitGroup
for _, v := range []time.Duration{5, 1} {
wg.Add(1)
go func() {
defer wg.Done()
wait(v, ch)
}()
}
wg.Wait()
}
func wait(seconds time.Duration, c chan time.Duration) {
time.Sleep(seconds * time.Second)
c <- seconds
}
However this results in a deadlock and I can't figure out why.
I have been trying to read the values after the WaitGroup with the following code:
close(ch)
for v := range ch {
fmt.Println(v)
}
However it seems it wouldn't even reach this part.
Thank you!
There are two problems withe the code:
You must close the channel only after all go-routines have finished
The value of v is being lost during the iteration
In go, the for loop will reuse v, so all go-routines will have the same value on the wait call.
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch := make(chan time.Duration)
var wg sync.WaitGroup
for _, v := range []time.Duration{5, 1} {
wg.Add(1)
v := v // <- this
go func() {
defer wg.Done()
wait(v, ch)
}()
}
go func() { // Close the channel only after go-routines finish
wg.Wait()
close(ch)
}()
for v := range ch { // Will loop until channel is closed
fmt.Println(v)
}
}
func wait(seconds time.Duration, c chan time.Duration) {
time.Sleep(seconds * time.Second)
c <- seconds
}
You need to close the worker channel after all the workers are done. You are closing it immediately from the main goroutine.
So do this:
go func() {
wg.Wait()
close(ch)
}()
Also your wait function already takes a time.Duration so really it should be in the real time at that point & not multiplied by time.Second. if you want to pass in units of seconds, consider changing the input type to int to avoid confusion.

Use channel to limit the number of active go routines

I'm reading the "The Go Programming Language"
One way to limit the number of running go routines is to use a "counting semaphore".
The other way is Limiting number of go routines running
I am allowing 2 more go routines in the case. I'm getting deadlock error.
What causes the deadlock in my code?
package main
import (
"bytes"
//"context"
"fmt"
"runtime"
"strconv"
"sync"
"time"
)
func main() {
max := 2
var wg sync.WaitGroup
squares := make(chan int)
tokens := make(chan struct{}, max)
for i := 20; i >= 1; i-- {
tokens <- struct{}{}
wg.Add(1)
go func(n int) {
defer func() { <-tokens }()
defer wg.Done()
fmt.Println("run go routine ", getGID())
squares <- Square(n)
}(i)
}
go func() {
wg.Wait()
close(squares)
}()
for s := range squares {
fmt.Println("Get square: ", s)
}
}
func Square(num int) int {
time.Sleep(time.Second * time.Duration(num))
fmt.Println(num * num)
return num * num
}
func getGID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
The goroutines block on sending to squares. Main is not receiving on squares because it blocks on starting the the goroutines.
Fix by moving the code that starts the goroutines to a goroutine. This allows main to continue executing to the receive on squares.
squares := make(chan int)
go func() {
max := 2
var wg sync.WaitGroup
tokens := make(chan struct{}, max)
for i := 20; i >= 1; i-- {
tokens <- struct{}{}
wg.Add(1)
go func(n int) {
defer func() { <-tokens }()
defer wg.Done()
fmt.Println("run go routine ", getGID())
squares <- Square(n)
}(i)
}
wg.Wait()
close(squares)
}()
fmt.Println("About to receive")
for s := range squares {
fmt.Println("Get square: ", s)
}
Run it on the playground.

All goroutines are asleep

I write some code which aims to synchronize using channel.
var counter int64 // shared resource
var wg sync.WaitGroup
func main() {
ch := make(chan int64)
wg.Add(2)
go incCounter(ch)
go incCounter(ch)
ch <- counter
wg.Wait()
fmt.Println("Final Counter:", counter) // expected value is 4
}
func incCounter(ch chan int64) {
defer wg.Done()
for count := 0; count < 2; count++ {
value := <-ch
value++
counter = value
ch <- counter
}
}
When I ran this program, an error happened: all goroutines are asleep - deadlock!. However I can't fix the problem and I don't know what is wrong. Could anyone help?
Channels make(chan int) has implicit size zero ( ref: https://golang.org/ref/spec#Making_slices_maps_and_channels)
A channel of size zero is unbuffered. A channel of specified size make(chan int, n) is buffered. See http://golang.org/ref/spec#Send_statements for a discussion on buffered vs. unbuffered channels. The example at http://play.golang.org/p/VZAiN1V8-P illustrates the difference.
Here, channel <-ch or ch <- will be blocked until someone processes it (concurrently). If you try the flow of this program in pen and paper, you will figure it out why it is blocked. Below figure shows possible data flow through channel ch:
So if you make your ch := make(chan int64) to ch := make(chan int64,1), it will work.
var counter int64 // shared resource
var wg sync.WaitGroup
func main() {
ch := make(chan int64, 1)
wg.Add(2)
go incCounter(ch)
go incCounter(ch)
ch <- counter
wg.Wait()
fmt.Println("Final Counter:", counter) // expected value is 4
}
func incCounter(ch chan int64) {
defer wg.Done()
for count := 0; count < 2; count++ {
value := <-ch
value++
counter = value
ch <- counter
}
}
If we analyse how program works when you are using ch := make(chan int64), we can see that one go routine is blocked in this program(another one is exited). With the help of time.Sleep(n) and receiving the last data from the channel in the blocked go routine, we can overcome the deadlock. See the code below:
var counter int64 // shared resource
var wg sync.WaitGroup
func main() {
ch := make(chan int64)
wg.Add(2)
go incCounter(ch)
go incCounter(ch)
ch <- counter
// to ensure one go routine 'incCounter' is completed and one go routine is blocked for unbuffered channel
time.Sleep(3*time.Second)
<-ch // to unblock the last go routine
wg.Wait()
fmt.Println("Final Counter:", counter) // expected value is 4
}
func incCounter(ch chan int64) {
defer wg.Done()
for count := 0; count < 2; count++ {
value := <-ch
value++
counter = value
ch <- counter
}
}

go routine for range over channels

I have been working in Golang for a long time. But still I am facing this problem though I know the solution to my problem. But never figured out why is it happening.
For example If I have a pipeline situation for inbound and outbound channels like below:
package main
import (
"fmt"
)
func main() {
for n := range sq(sq(gen(3, 4))) {
fmt.Println(n)
}
fmt.Println("Process completed")
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
It does not give me a deadlock situation. But if I remove the go routine inside the outbound code as below:
func sq(in <-chan int) <-chan int {
out := make(chan int)
for n := range in {
out <- n * n
}
close(out)
return out
}
I received a deadlock error. Why is it so that looping over channels using range without go routine gives a deadlock.
This situation caused of output channel of sq function is not buffered. So sq is waiting until next function will read from output, but if sq is not async, it will not happen (Playground link):
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
numsCh := gen(3, 4)
sqCh := sq(numsCh) // if there is no sq in body - we are locked here until input channel will be closed
result := sq(sqCh) // but if output channel is not buffered, so `sq` is locked, until next function will read from output channel
for n := range result {
fmt.Println(n)
}
fmt.Println("Process completed")
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func sq(in <-chan int) <-chan int {
out := make(chan int, 100)
for n := range in {
out <- n * n
}
close(out)
return out
}
Your function creates a channel, writes to it, then returns it. The writing will block until somebody can read the corresponding value, but that's impossible because nobody outside this function has the channel yet.
func sq(in <-chan int) <-chan int {
// Nobody else has this channel yet...
out := make(chan int)
for n := range in {
// ...but this line will block until somebody reads the value...
out <- n * n
}
close(out)
// ...and nobody else can possibly read it until after this return.
return out
}
If you wrap the loop in a goroutine then both the loop and the sq function are allowed to continue; even if the loop blocks, the return out statement can still go and eventually you'll be able to connect up a reader to the channel.
(There's nothing intrinsically bad about looping over channels outside of goroutines; your main function does it harmlessly and correctly.)
The reason of the deadlock is because the main is waiting for the sq return and finish, but the sq is waiting for someone read the chan then it can continue.
I simplified your code by removing layer of sq call, and split one sentence into 2 :
func main() {
result := sq(gen(3, 4)) // <-- block here, because sq doesn't return
for n := range result {
fmt.Println(n)
}
fmt.Println("Process completed")
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func sq(in <-chan int) <-chan int {
out := make(chan int)
for n := range in {
out <- n * n // <-- block here, because no one is reading from the chan
}
close(out)
return out
}
In sq method, if you put code in goroutine, then the sq will returned, and main func will not block, and consume the result queue, and the goroutine will continue, then there is no block any more.
func main() {
result := sq(gen(3, 4)) // will not blcok here, because the sq just start a goroutine and return
for n := range result {
fmt.Println(n)
}
fmt.Println("Process completed")
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n // will not block here, because main will continue and read the out chan
}
close(out)
}()
return out
}
The code is a bit complicated,
Let's simplify
First eq below, not has deadLock
func main() {
send := make(chan int)
receive := make(chan int)
go func() {
send<-3
send<-4
close(send)
}()
go func() {
receive<- <-send
receive<- <-send
close(receive)
}()
for v := range receive{
fmt.Println(v)
}
}
Second eq below,remove "go" has deadLock
func main() {
send := make(chan int)
receive := make(chan int)
go func() {
send<-3
send<-4
close(send)
}()
receive<- <-send
receive<- <-send
close(receive)
for v := range receive{
fmt.Println(v)
}
}
Let's simplify second code again
func main() {
ch := make(chan int)
ch <- 3
ch <- 4
close(ch)
for v := range ch{
fmt.Println(v)
}
}
The reason of the deadlock is no buffer channel waiting in main goroutine.
Two Solutions
// add more cap then "channel<-" time
func main() {
ch := make(chan int,2)
ch <- 3
ch <- 4
close(ch)
for v := range ch{
fmt.Println(v)
}
}
//async "<-channel"
func main() {
ch := make(chan int)
go func() {
for v := range ch {
fmt.Println(v)
}
}()
ch <- 3
ch <- 4
close(ch)
}
My understanding is
when the main thread is blocked for waiting for the chan to be writen or read, Go will detect if any other Go routine is running. If there is no any other Go routine running, it will have "fatal error: all goroutines are asleep - deadlock!"
I tested if by using the below simple case
func main() {
c := make(chan int)
go func() {
time.Sleep(10 * time.Second)
}()
c <- 1
}
The deadlock error is reported after 10 seconds.

Golang - signal other goroutines to stop and return when one goroutine has found the result

I would like to speed up a certain task in Go by starting several worker goroutines.
In the example below, I'm looking for a "treasure". Worker goroutines that are started will dig forever for items until they are told to stop. If the item is a wanted treasure, then it is placed onto a shared buffered channel with a capacity equals to the number of workers.
The program is only interested in getting one treasure. It also has to make sure that all workers goroutines will return and not be blocked forever.
The example works, but is there a cleaner or more idiomatic way to ensuring the above?
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var wg sync.WaitGroup
func digTreasure() int {
time.Sleep(5 * time.Millisecond)
return rand.Intn(1000)
}
func worker(i int, ch chan int, quit chan struct{}) {
defer func() {
fmt.Println("worker", i, "left")
wg.Done()
}()
for {
treasure := digTreasure()
if treasure%100 == 0 {
fmt.Println("worker", i, "found treasure", treasure)
ch <- treasure
return
}
select {
case <-quit:
fmt.Println("worker", i, "quitting")
return
default:
}
}
}
func main() {
rand.Seed(time.Now().UnixNano())
n := 10
ch, quit := make(chan int, n), make(chan struct{})
fmt.Println("Searching...")
wg.Add(n)
for i := 0; i < n; i++ {
go worker(i, ch, quit)
}
fmt.Println("I found treasure:", <-ch)
close(quit)
wg.Wait()
fmt.Println("All workers left")
}

Resources