All channels are deadlocked - go

I'm trying to use a for loop that continuously sends strings to different channels read by different goroutines. However, it gives me the error "all goroutines are asleep - deadlock!" Why is this happening? I searched for some answers, but I couldn't find an answer for this situation.
func main() {
var chans []chan string
for i := 0; i < 3; i++ {
chans = append(chans, make(chan string))
}
for i := 0; i < 3; i++ {
go sendString(chans[i])
}
for str := range chans[0] {
fmt.Print(str)
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
}
The errors are here. It prints "abcd", then generates the error, and if I delete the loop for printing, the program does not generate the error.
abcdfatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:18 +0x28d
goroutine 19 [chan send]:
main.sendString(0xc04203c120)
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:24 +0x42
created by main.main
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:15 +0x175
goroutine 20 [chan send]:
main.sendString(0xc04203c180)
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:24 +0x42
created by main.main
C:/Users/YuanZheng Hu/Desktop/Go Test/test/test.go:15 +0x175
exit status 2
I did the version using WaitGroup, but it seems not correct, and gives me the same error " all goroutines are asleep - deadlock!" where did I do wrong in the code below ?
func main() {
var myWaitGroup sync.WaitGroup
ch := make(chan string)
myWaitGroup.Add(1)
go sendString(ch, &myWaitGroup)
myWaitGroup.Wait()
close(ch)
time.Sleep(1 * time.Second)
}
func sendString(ch chan string, pg *sync.WaitGroup) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
defer pg.Done()
}

The second for loop will block until the channel is closed so you need to close it in the sending function. Also, you only read from the first channel so some of the data is lost. Doing this:
func main() {
var chans []chan string
for i := 0; i < 3; i++ {
chans = append(chans, make(chan string))
}
for i := 0; i < 3; i++ {
go sendString(chans[i])
}
for i := 0; i < 3; i++ {
for str := range chans[i] {
fmt.Print(str)
}
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
close(ch)
}
Will produce:
abcdabcdabcd
https://play.golang.org/p/7SoDKChnTbz
If you wanted to do this with a single channel as per your comment then you could add a wait group to close the channel once all the go routines are complete:
func main() {
c := make(chan string)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
sendString(c)
wg.Done()
}()
}
go func() {
wg.Wait()
close(c)
}()
for str := range c {
fmt.Print(str)
}
}
func sendString(ch chan string) {
ch <- "a"
ch <- "b"
ch <- "c"
ch <- "d"
}
https://play.golang.org/p/E_awt8UBK9v

Related

All goroutines are asleep when reading from buffered channel

func writeToChan(wg *sync.WaitGroup, ch chan int, stop int) {
defer wg.Done()
for i := 0; i < stop; i++ {
ch <- i
}
}
func readToChan(wg *sync.WaitGroup, ch chan int) {
defer wg.Done()
for n := range ch {
fmt.Println(n)
}
}
func main() {
ch := make(chan int, 3)
wg := new(sync.WaitGroup)
wg.Add(2)
go writeToChan(wg, ch, 5)
go readToChan(wg, ch)
wg.Wait()
}
0
1
2
3
4
fatal error: all goroutines are asleep - deadlock!
I assume that the readToChan always reads continuously, and the writeToChan write to the channel and waits while the channel is read.
I don't know why the output showed deadlock while I added two 'wait' to the WaitGroup.
You need to close channel at the sender side.
By using
for n := range ch {
fmt.Println(n)
}
The loop will only stop when ch is closed
correct example:
package main
import (
"fmt"
"sync"
)
func writeToChan(wg *sync.WaitGroup, ch chan int, stop int) {
defer wg.Done()
for i := 0; i < stop; i++ {
ch <- i
}
close(ch)
}
func readToChan(wg *sync.WaitGroup, ch chan int) {
defer wg.Done()
for n := range ch {
fmt.Println(n)
}
}
func main() {
ch := make(chan int, 3)
wg := new(sync.WaitGroup)
wg.Add(2)
go writeToChan(wg, ch, 5)
go readToChan(wg, ch)
wg.Wait()
}
If close is not called on buffered channel, reader doesn't know when to stop reading.
Check this example with for and select calls(to handle multi channels).
https://go.dev/play/p/Lx5g9o4RsqW
package main
import (
"fmt"
"sync"
"time")
func writeToChan(wg *sync.WaitGroup, ch chan int, stop int, quit chan<- bool) {
defer func() {
wg.Done()
close(ch)
fmt.Println("write wg done")
}()
for i := 0; i < stop; i++ {
ch <- i
fmt.Println("write:", i)
}
fmt.Println("write done")
fmt.Println("sleeping for 5 sec")
time.Sleep(5 * time.Second)
quit <- true
close(quit)
}
func readToChan(wg *sync.WaitGroup, ch chan int, quit chan bool) {
defer func() {
wg.Done()
fmt.Println("read wg done")
}()
//using rang over
//for n := range ch {
// fmt.Println(n)
//}
//using Select if you have multiple channels.
for {
//fmt.Println("waiting for multiple channels")
select {
case n := <-ch:
fmt.Println("read:", n)
// if ok == false {
// fmt.Println("read done")
// //return
// }
case val := <-quit:
fmt.Println("received quit :", val)
return
// default:
// fmt.Println("default")
}
}
}
func main() {
ch := make(chan int, 5)
ch2 := make(chan bool)
wg := new(sync.WaitGroup)
wg.Add(2)
go writeToChan(wg, ch, 3, ch2)
go readToChan(wg, ch, ch2)
wg.Wait()
}
Output:
write: 0
write: 1
write: 2
write done
sleeping for 5 sec
read: 0
read: 1
read: 2
write wg done
received quit : true
read wg done
Program exited.

Go:How to print dog, cat and fish alternately for 3 times through 3 goroutine without deadlock?

1.How to use sync.WaitGroup to solve deadlock?
My code can print the result correctly, but it will cause deadlock.
What I can think of now is:replace sync.WaitGroup with time.Sleep.
But I want to know how to use sync.WaitGroup to solve deadlock?
This is the result of the run:
dog: 0
cat: 0
fish: 0
dog: 1
cat: 1
fish: 1
dog: 2
cat: 2
fish: 2
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xeaeeb0)
D:/GoSDK/go1.17.3/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0x60)
D:/GoSDK/go1.17.3/src/sync/waitgroup.go:130 +0x71
This is my code:
func main(){
wg := sync.WaitGroup{}
wg.Add(3)
const Count = 3
ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
<-ch1
fmt.Println("dog:", i)
//notice 2
ch2 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 1
<-ch2
fmt.Println("cat:", i)
//notice 3
ch3 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 2
<-ch3
fmt.Println("fish:", i)
//notice 1
ch1 <- true
}
}()
//notic 1
ch1 <- true
wg.Wait()
}
The issue here is that no go routine is waiting for ch1. So on the last iteration of the third goroutine locks (ch1 <- true).
So what you need is a way to recognize that the chain stopped.
My fast and humble suggestion:
func main() {
wg := sync.WaitGroup{}
wg.Add(3)
const Count = 3
ch1, ch2, ch3 := make(chan bool), make(chan bool), make(chan bool)
chainEnded := make(chan struct{})
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
<-ch1
fmt.Println("dog:", i)
//notice 2
ch2 <- true
}
chainEnded <- struct{}{}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 1
<-ch2
fmt.Println("cat:", i)
//notice 3
ch3 <- true
}
}()
go func() {
defer wg.Done()
for i := 0; i < Count; i++ {
//wait 2
<-ch3
fmt.Println("fish:", i)
//notice 1
ch1 <- true
}
}()
//notic 1
ch1 <- true
<-chainEnded // wait for the loop to end and send to this chan
<-ch1 // unblock the attempt to chain of the last routine
wg.Wait()
}

golang goroutines, chanel and sync.WaitGroup

I use simple code, but I get deadlock all the time.
Please explain to the beginner what I am doing wrong.
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
ok := make(chan int, 3)
for i := 0; i < 2; i++ {
wg.Add(1)
go func(i int, wg *sync.WaitGroup) {
for x := range ok {
fmt.Println(i, x)
if x >= 5 {
ok <- x - 1
}
}
wg.Done()
}(i, &wg)
}
ok <- 1
ok <- 3
ok <- 2
ok <- 5
ok <- 3
ok <- 9
wg.Wait()
}
fatal error: all goroutines are asleep - deadlock!
The background of the problem is that the range operator reads from the channel until the channel is closed. Hence the for-range loop keeps waiting for more input from the channel ok even though there are no more inputs to come at some point. At the same time wg.Wait() is waiting for the goroutines to finish. Hence a deadlock!
Either you'll have to close the ok channel at some point, where
there are no more incoming values to the channel ok.
Or you may use the worker pool just like,
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, ch chan string, i int) {
defer wg.Done()
ch <- "worker process value " + strconv.Itoa(i)
}
func workerMonitor(wg *sync.WaitGroup, ch chan string) {
wg.Wait()
close(ch)
}
func doWork(ch <-chan string, done chan<- bool) {
for i := range ch {
fmt.Println(i)
}
done <- true
}
func main() {
var wg sync.WaitGroup
ch := make(chan string)
var arr = [6]int{1, 3, 2, 5, 3, 9}
for i := 0; i < len(arr); i++ {
wg.Add(1)
if arr[i] >= 5 {
for j := arr[i]; j >= 5; j-- {
wg.Add(1)
go worker(&wg, ch, j-1)
}
}
go worker(&wg, ch, arr[i])
}
go workerMonitor(&wg, ch)
done := make(chan bool, 1)
go doWork(ch, done)
<-done
}
Play ground url

WaitGroup deadlock (without error message) [duplicate]

package main
import (
"fmt"
"sync"
)
func push(c chan int,wg sync.WaitGroup) {
for i := 0; i < 5; i++ {
c <- i
}
wg.Done()
}
func pull(c chan int,wg sync.WaitGroup) {
for i := 0; i < 5; i++ {
result,ok := <- c
fmt.Println(result,ok)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)
go push(c,wg)
go pull(c,wg)
wg.Wait()
}
Output:
localhost:src kuankuan$ go run goroutine.go
0 true
1 true
2 true
3 true
4 true
throw: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x42130100, 0x42130100)
/usr/local/go/src/pkg/runtime/zsema_amd64.c:146 +0x25
sync.(*WaitGroup).Wait(0x42120420, 0x0)
/usr/local/go/src/pkg/sync/waitgroup.go:79 +0xf2
main.main()
/Users/kuankuan/go/src/goroutine.go:31 +0xb9
goroutine 2 [syscall]:
created by runtime.main
/usr/local/go/src/pkg/runtime/proc.c:221
exit status 2
The reason why it deadlocks is because structs are passed by value and not by reference.
When you pass the WaitGroup to your functions, you need to pass the pointer and not the value. Otherwise a copy of the WaitGroup will be used.
This is your working example:
package main
import (
"fmt"
"sync"
)
func push(c chan int,wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
c <- i
}
wg.Done()
}
func pull(c chan int,wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
result,ok := <- c
fmt.Println(result,ok)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)
go push(c,&wg)
go pull(c,&wg)
wg.Wait()
}

Why my golang channel raise dead lock error?

package main
import (
"fmt"
"sync"
)
func push(c chan int,wg sync.WaitGroup) {
for i := 0; i < 5; i++ {
c <- i
}
wg.Done()
}
func pull(c chan int,wg sync.WaitGroup) {
for i := 0; i < 5; i++ {
result,ok := <- c
fmt.Println(result,ok)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)
go push(c,wg)
go pull(c,wg)
wg.Wait()
}
Output:
localhost:src kuankuan$ go run goroutine.go
0 true
1 true
2 true
3 true
4 true
throw: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x42130100, 0x42130100)
/usr/local/go/src/pkg/runtime/zsema_amd64.c:146 +0x25
sync.(*WaitGroup).Wait(0x42120420, 0x0)
/usr/local/go/src/pkg/sync/waitgroup.go:79 +0xf2
main.main()
/Users/kuankuan/go/src/goroutine.go:31 +0xb9
goroutine 2 [syscall]:
created by runtime.main
/usr/local/go/src/pkg/runtime/proc.c:221
exit status 2
The reason why it deadlocks is because structs are passed by value and not by reference.
When you pass the WaitGroup to your functions, you need to pass the pointer and not the value. Otherwise a copy of the WaitGroup will be used.
This is your working example:
package main
import (
"fmt"
"sync"
)
func push(c chan int,wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
c <- i
}
wg.Done()
}
func pull(c chan int,wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
result,ok := <- c
fmt.Println(result,ok)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)
go push(c,&wg)
go pull(c,&wg)
wg.Wait()
}

Resources