为什么我的 Golang 通道会出现死锁错误?

huangapple go评论85阅读模式
英文:

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

}

英文:
package main

import (
	&quot;fmt&quot;
    &quot;sync&quot;
)

func push(c chan int,wg sync.WaitGroup) {
	for i := 0; i &lt; 5; i++ {
		c &lt;- i
	}
    wg.Done()
}

func pull(c chan int,wg sync.WaitGroup) {
    for i := 0; i &lt; 5; i++ {
        result,ok := &lt;- 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

答案1

得分: 23

死锁的原因是因为结构体是按值传递而不是按引用传递。

当将WaitGroup传递给函数时,需要传递指针而不是值。否则,将使用WaitGroup的副本。

这是您的工作示例:

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()
}
英文:

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 (
    &quot;fmt&quot;
    &quot;sync&quot;
)

func push(c chan int,wg *sync.WaitGroup) {
    for i := 0; i &lt; 5; i++ {
        c &lt;- i
    }
    wg.Done()
}

func pull(c chan int,wg *sync.WaitGroup) {
    for i := 0; i &lt; 5; i++ {
        result,ok := &lt;- c
        fmt.Println(result,ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)
	
    go push(c,&amp;wg)
    go pull(c,&amp;wg)

    wg.Wait()
}

huangapple
  • 本文由 发表于 2012年11月26日 21:42:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/13566065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定