Why my golang channel raise dead lock error? - go

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

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.

golang chanel not working with sync.WaitGroup

my code
package main
import (
"fmt"
"sync"
)
func other(c chan int, wg *sync.WaitGroup) {
c <- 455
wg.Done()
}
func addInt(c chan int, d int, wg *sync.WaitGroup) {
c <- d
wg.Done()
}
func main() {
var wg sync.WaitGroup
myChanel := make(chan int)
wg.Add(2)
go addInt(myChanel, 5, &wg)
go other(myChanel, &wg)
wg.Wait()
c := 0
for v := range myChanel {
if c == 1 {
close(myChanel)
}
fmt.Println(v)
c++
}
}
I am learning golang looking at mines, but it is true I got such an error. I looked at other sources. I couldn't reach a healthy solution. I tried shutdown (Chanel) again.
error output
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000140f8)
/usr/lib/go-1.13/src/runtime/sema.go:56 +0x42
sync.(*WaitGroup).Wait(0xc0000140f0)
/usr/lib/go-1.13/src/sync/waitgroup.go:130 +0x64
main.main()
/home/zeus/go/src/github.com/awesomeProject/pool.go:27 +0xe4
goroutine 6 [chan send]:
main.addInt(0xc000016120, 0x5, 0xc0000140f0)
/home/zeus/go/src/github.com/awesomeProject/pool.go:14 +0x3f
created by main.main
/home/zeus/go/src/github.com/awesomeProject/pool.go:24 +0xaa
goroutine 7 [chan send]:
main.other(0xc000016120, 0xc0000140f0)
/home/zeus/go/src/github.com/awesomeProject/pool.go:9 +0x37
created by main.main
/home/zeus/go/src/github.com/awesomeProject/pool.go:25 +0xd6
exit status 2
You have an unbuffered channel, which means you can't send on it until there is something waiting to receive.
So when you do:
wg.Wait()
before you do
for v := range myChanel
you'll never be able to get to the receiver.
I've never needed to use a waitgroup when using unbuffered channels anyways, in my experience you only need them when doing concurrent stuff without channels. You can just do it like this: https://play.golang.org/p/-SUuXGlFd1E
ı solved it
run it
package main
import (
"fmt"
"sync"
"time"
)
func other(c chan int, wg *sync.WaitGroup) {
time.Sleep(time.Second*1)
c <- 455
wg.Done()
}
func addInt(c chan int, d int, wg *sync.WaitGroup) {
c <- d
wg.Done()
}
func main() {
var wg sync.WaitGroup
myChanel := make(chan int)
wg.Add(2)
go addInt(myChanel, 5, &wg)
go other(myChanel, &wg)
go func() {
wg.Wait()
close(myChanel)
}()
for v := range myChanel {
fmt.Println(v)
}
}

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

All channels are deadlocked

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

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

Resources